file_manager: don't emit events when a node is processing metadata
When a folder is copied processing can take several minutes, depending on the size and number of gcode files in the path. Suppress all file events on a node until processing is complete. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
b3d2307d36
commit
cfa5f4a432
@ -736,6 +736,7 @@ class InotifyNode:
|
|||||||
self.pending_node_events: Dict[str, asyncio.Handle] = {}
|
self.pending_node_events: Dict[str, asyncio.Handle] = {}
|
||||||
self.pending_deleted_children: Set[Tuple[str, bool]] = set()
|
self.pending_deleted_children: Set[Tuple[str, bool]] = set()
|
||||||
self.pending_file_events: Dict[str, str] = {}
|
self.pending_file_events: Dict[str, str] = {}
|
||||||
|
self.is_processing_metadata = False
|
||||||
|
|
||||||
async def _finish_create_node(self) -> None:
|
async def _finish_create_node(self) -> None:
|
||||||
# Finish a node's creation. All children that were created
|
# Finish a node's creation. All children that were created
|
||||||
@ -748,10 +749,12 @@ class InotifyNode:
|
|||||||
node_path = self.get_path()
|
node_path = self.get_path()
|
||||||
root = self.get_root()
|
root = self.get_root()
|
||||||
# Scan child nodes for unwatched directories and metadata
|
# Scan child nodes for unwatched directories and metadata
|
||||||
|
self.is_processing_metadata = True
|
||||||
mevts: List[asyncio.Event] = self.scan_node()
|
mevts: List[asyncio.Event] = self.scan_node()
|
||||||
if mevts:
|
if mevts:
|
||||||
mfuts = [e.wait() for e in mevts]
|
mfuts = [e.wait() for e in mevts]
|
||||||
await asyncio.gather(*mfuts)
|
await asyncio.gather(*mfuts)
|
||||||
|
self.is_processing_metadata = False
|
||||||
self.ihdlr.log_nodes()
|
self.ihdlr.log_nodes()
|
||||||
self.ihdlr.notify_filelist_changed(
|
self.ihdlr.notify_filelist_changed(
|
||||||
"create_dir", root, node_path)
|
"create_dir", root, node_path)
|
||||||
@ -836,6 +839,10 @@ class InotifyNode:
|
|||||||
if evt_name is None:
|
if evt_name is None:
|
||||||
logging.info(f"Invalid file write event: {file_name}")
|
logging.info(f"Invalid file write event: {file_name}")
|
||||||
return
|
return
|
||||||
|
if self.is_processing():
|
||||||
|
logging.debug("Metadata is processing, suppressing write "
|
||||||
|
f"event: {file_name}")
|
||||||
|
return
|
||||||
pending_node = self.search_pending_event("create_node")
|
pending_node = self.search_pending_event("create_node")
|
||||||
if pending_node is not None:
|
if pending_node is not None:
|
||||||
# if this event was generated as a result of a created parent
|
# if this event was generated as a result of a created parent
|
||||||
@ -902,6 +909,11 @@ class InotifyNode:
|
|||||||
def get_root(self) -> str:
|
def get_root(self) -> str:
|
||||||
return self.parent_node.get_root()
|
return self.parent_node.get_root()
|
||||||
|
|
||||||
|
def is_processing(self) -> bool:
|
||||||
|
if self.is_processing_metadata:
|
||||||
|
return True
|
||||||
|
return self.parent_node.is_processing()
|
||||||
|
|
||||||
def add_event(self, evt_name: str, timeout: float) -> None:
|
def add_event(self, evt_name: str, timeout: float) -> None:
|
||||||
if evt_name in self.pending_node_events:
|
if evt_name in self.pending_node_events:
|
||||||
self.reset_event(evt_name, timeout)
|
self.reset_event(evt_name, timeout)
|
||||||
@ -963,6 +975,9 @@ class InotifyRootNode(InotifyNode):
|
|||||||
return self
|
return self
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def is_processing(self) -> bool:
|
||||||
|
return self.is_processing_metadata
|
||||||
|
|
||||||
class NotifySyncLock:
|
class NotifySyncLock:
|
||||||
def __init__(self, dest_path: str) -> None:
|
def __init__(self, dest_path: str) -> None:
|
||||||
self.wait_fut: Optional[asyncio.Future] = None
|
self.wait_fut: Optional[asyncio.Future] = None
|
||||||
@ -1281,6 +1296,8 @@ class INotifyHandler:
|
|||||||
logging.debug(f"Inotify file move to: {root}, "
|
logging.debug(f"Inotify file move to: {root}, "
|
||||||
f"{node_path}, {evt.name}")
|
f"{node_path}, {evt.name}")
|
||||||
moved_evt = self.pending_moves.pop(evt.cookie, None)
|
moved_evt = self.pending_moves.pop(evt.cookie, None)
|
||||||
|
# Don't emit file events if the node is processing metadata
|
||||||
|
can_notify = not node.is_processing()
|
||||||
if moved_evt is not None:
|
if moved_evt is not None:
|
||||||
# Moved from a currently watched directory
|
# Moved from a currently watched directory
|
||||||
prev_parent, prev_name, hdl = moved_evt
|
prev_parent, prev_name, hdl = moved_evt
|
||||||
@ -1293,15 +1310,20 @@ class INotifyHandler:
|
|||||||
# Unable to move, metadata needs parsing
|
# Unable to move, metadata needs parsing
|
||||||
mevt = self.parse_gcode_metadata(file_path)
|
mevt = self.parse_gcode_metadata(file_path)
|
||||||
await mevt.wait()
|
await mevt.wait()
|
||||||
self.notify_filelist_changed(
|
if can_notify:
|
||||||
"move_file", root, file_path,
|
self.notify_filelist_changed(
|
||||||
prev_root, prev_path)
|
"move_file", root, file_path,
|
||||||
|
prev_root, prev_path)
|
||||||
else:
|
else:
|
||||||
if root == "gcodes":
|
if root == "gcodes":
|
||||||
mevt = self.parse_gcode_metadata(file_path)
|
mevt = self.parse_gcode_metadata(file_path)
|
||||||
await mevt.wait()
|
await mevt.wait()
|
||||||
self.notify_filelist_changed(
|
if can_notify:
|
||||||
"create_file", root, file_path)
|
self.notify_filelist_changed(
|
||||||
|
"create_file", root, file_path)
|
||||||
|
if not can_notify:
|
||||||
|
logging.debug("Metadata is processing, suppressing move "
|
||||||
|
f"notification: {file_path}")
|
||||||
elif evt.mask & iFlags.MODIFY:
|
elif evt.mask & iFlags.MODIFY:
|
||||||
node.schedule_file_event(evt.name, "modify_file")
|
node.schedule_file_event(evt.name, "modify_file")
|
||||||
elif evt.mask & iFlags.CLOSE_WRITE:
|
elif evt.mask & iFlags.CLOSE_WRITE:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user