/api/watch also continuously reports disk usage

This commit is contained in:
Leo Vasanko 2023-10-23 05:24:54 +03:00 committed by Leo Vasanko
parent 4852212347
commit 5d3f419508
2 changed files with 27 additions and 11 deletions

View File

@ -77,8 +77,9 @@ async def watch(req, ws):
try: try:
with watching.tree_lock: with watching.tree_lock:
q = watching.pubsub[ws] = asyncio.Queue() q = watching.pubsub[ws] = asyncio.Queue()
# Init with full tree # Init with disk usage and full tree
await ws.send(watching.refresh()) await ws.send(watching.format_du())
await ws.send(watching.format_tree())
# Send updates # Send updates
while True: while True:
await ws.send(await q.get()) await ws.send(await q.get())

View File

@ -1,4 +1,5 @@
import asyncio import asyncio
import shutil
import threading import threading
import time import time
from pathlib import Path, PurePosixPath from pathlib import Path, PurePosixPath
@ -8,7 +9,6 @@ import msgspec
from cista import config from cista import config
from cista.protocol import DirEntry, FileEntry, UpdateEntry from cista.protocol import DirEntry, FileEntry, UpdateEntry
from cista.util.apphelpers import websocket_wrapper
pubsub = {} pubsub = {}
tree = {"": None} tree = {"": None}
@ -16,15 +16,18 @@ tree_lock = threading.Lock()
rootpath = None rootpath = None
quit = False quit = False
modified_flags = "IN_CREATE", "IN_DELETE", "IN_DELETE_SELF", "IN_MODIFY", "IN_MOVE_SELF", "IN_MOVED_FROM", "IN_MOVED_TO" modified_flags = "IN_CREATE", "IN_DELETE", "IN_DELETE_SELF", "IN_MODIFY", "IN_MOVE_SELF", "IN_MOVED_FROM", "IN_MOVED_TO"
disk_usage = None
def watcher_thread(loop): def watcher_thread(loop):
global disk_usage
while True: while True:
i = inotify.adapters.InotifyTree(rootpath.as_posix()) i = inotify.adapters.InotifyTree(rootpath.as_posix())
old = refresh() if tree[""] else None old = format_tree() if tree[""] else None
with tree_lock: with tree_lock:
# Initialize the tree from filesystem # Initialize the tree from filesystem
tree[""] = walk(rootpath) tree[""] = walk(rootpath)
msg = refresh() msg = format_tree()
if msg != old: if msg != old:
asyncio.run_coroutine_threadsafe(broadcast(msg), loop) asyncio.run_coroutine_threadsafe(broadcast(msg), loop)
@ -33,6 +36,10 @@ def watcher_thread(loop):
for event in i.event_gen(): for event in i.event_gen():
if quit: return if quit: return
du = shutil.disk_usage(rootpath)
if du != disk_usage:
disk_usage = du
asyncio.run_coroutine_threadsafe(broadcast(format_du()), loop)
if time.monotonic() > refreshdl: break if time.monotonic() > refreshdl: break
if event is None: continue if event is None: continue
_, flags, path, filename = event _, flags, path, filename = event
@ -43,6 +50,20 @@ def watcher_thread(loop):
update(path.relative_to(rootpath), loop) update(path.relative_to(rootpath), loop)
i = None # Free the inotify object i = None # Free the inotify object
def format_du():
return msgspec.json.encode({"space": {
"disk": disk_usage.total,
"used": disk_usage.used,
"free": disk_usage.free,
"storage": tree[""].size,
}}).decode()
def format_tree():
root = tree[""]
return msgspec.json.encode({"update": [
UpdateEntry(size=root.size, mtime=root.mtime, dir=root.dir)
]}).decode()
def walk(path: Path) -> DirEntry | FileEntry | None: def walk(path: Path) -> DirEntry | FileEntry | None:
try: try:
s = path.stat() s = path.stat()
@ -63,12 +84,6 @@ def walk(path: Path) -> DirEntry | FileEntry | None:
print("OS error walking path", path, e) print("OS error walking path", path, e)
return None return None
def refresh():
root = tree[""]
return msgspec.json.encode({"update": [
UpdateEntry(size=root.size, mtime=root.mtime, dir=root.dir)
]}).decode()
def update(relpath: Path, loop): def update(relpath: Path, loop):
"""Called by inotify updates, check the filesystem and broadcast any changes.""" """Called by inotify updates, check the filesystem and broadcast any changes."""
new = walk(rootpath / relpath) new = walk(rootpath / relpath)