From fce056e48133228f635048776e0381990b363a57 Mon Sep 17 00:00:00 2001 From: Eric Callahan Date: Wed, 22 Feb 2023 15:42:07 -0500 Subject: [PATCH] file_manager: fix notification sync on fast machines Desktop class PCs may exit the request before the inotify observer gains control of the loop. When the observer does gain control it will immediately notify as the sync mutex is no longer held, this can result in sending the websocket notification before the response has returned. Delay all notifications by 5ms to prevent this. Signed-off-by: Eric Callahan --- .../components/file_manager/file_manager.py | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/moonraker/components/file_manager/file_manager.py b/moonraker/components/file_manager/file_manager.py index 04c49a6..adf82c3 100644 --- a/moonraker/components/file_manager/file_manager.py +++ b/moonraker/components/file_manager/file_manager.py @@ -792,7 +792,7 @@ class FileManager: except Exception: pass raise - return result + return result def _parse_upload_args(self, upload_args: Dict[str, Any] @@ -2144,23 +2144,19 @@ class InotifyObserver(BaseFileSystemObserver): source_root, source_path) result['source_item'] = {'path': src_rel_path, 'root': source_root} key = f"{action}-{root}-{rel_path}" - if sync_fut is not None: - # Delay this notification so that it occurs after an item - logging.debug(f"Syncing notification: {full_path}") - self.event_loop.register_callback( - self._sync_with_request, result, sync_fut, key - ) - else: - self.file_manager.cancel_notification(key) - self.server.send_event("file_manager:filelist_changed", result) + self.event_loop.create_task( + self._finish_notify(result, sync_fut, key) + ) - async def _sync_with_request( + async def _finish_notify( self, result: Dict[str, Any], - sync_fut: asyncio.Future, + sync_fut: Optional[asyncio.Future], notify_key: str ) -> None: - await sync_fut + if sync_fut is not None: + logging.debug(f"Syncing notification: {notify_key}") + await sync_fut self.file_manager.cancel_notification(notify_key) await asyncio.sleep(.005) self.server.send_event("file_manager:filelist_changed", result)