diff --git a/src/electionguard_gui/components/guardian_home_component.py b/src/electionguard_gui/components/guardian_home_component.py index ab874687..23d8bd03 100644 --- a/src/electionguard_gui/components/guardian_home_component.py +++ b/src/electionguard_gui/components/guardian_home_component.py @@ -49,10 +49,18 @@ def get_key_ceremonies(self) -> dict[str, Any]: return eel_success(js_key_ceremonies) def watch_db_collections(self) -> None: - self._log.debug("Watching database") - db = self._db_service.get_db() - self._db_watcher_service.watch_database(db, None, notify_ui_db_changed) - self._log.debug("exited watching database") + try: + self._log.debug("Watching database") + db = self._db_service.get_db() + self._db_watcher_service.watch_database(db, None, notify_ui_db_changed) + self._log.debug("exited watching database") + except KeyboardInterrupt: + self._log.debug("Keyboard interrupt, exiting watch database") + self._db_watcher_service.stop_watching() + except Exception as e: # pylint: disable=broad-except + self.handle_error(e) + self._db_watcher_service.stop_watching() + # no need to raise exception or return anything, we're in fire-and-forget mode here def stop_watching_db_collections(self) -> None: self._log.debug("Stopping watch database") diff --git a/src/electionguard_gui/components/key_ceremony_details_component.py b/src/electionguard_gui/components/key_ceremony_details_component.py index a9befd9f..59c27058 100644 --- a/src/electionguard_gui/components/key_ceremony_details_component.py +++ b/src/electionguard_gui/components/key_ceremony_details_component.py @@ -70,14 +70,22 @@ def expose(self) -> None: eel.expose(self.stop_watching_key_ceremony) def watch_key_ceremony(self, key_ceremony_id: str) -> None: - db = self._db_service.get_db() - # retrieve and send the key ceremony to the client - self.on_key_ceremony_changed("key_ceremonies", key_ceremony_id) - self._log.debug(f"watching key ceremony '{key_ceremony_id}'") - # start watching for key ceremony changes from guardians - self._db_watcher_service.watch_database( - db, key_ceremony_id, self.on_key_ceremony_changed - ) + try: + db = self._db_service.get_db() + # retrieve and send the key ceremony to the client + self.on_key_ceremony_changed("key_ceremonies", key_ceremony_id) + self._log.debug(f"watching key ceremony '{key_ceremony_id}'") + # start watching for key ceremony changes from guardians + self._db_watcher_service.watch_database( + db, key_ceremony_id, self.on_key_ceremony_changed + ) + except KeyboardInterrupt: + self._log.debug("Keyboard interrupt, exiting watch database") + self._db_watcher_service.stop_watching() + except Exception as e: # pylint: disable=broad-except + self.handle_error(e) + self._db_watcher_service.stop_watching() + # we're in a fire-and-forget scenario, so no need to raise an exception or return anything def stop_watching_key_ceremony(self) -> None: self._db_watcher_service.stop_watching() diff --git a/src/electionguard_gui/main_app.py b/src/electionguard_gui/main_app.py index 80bef36f..0482c75f 100644 --- a/src/electionguard_gui/main_app.py +++ b/src/electionguard_gui/main_app.py @@ -101,8 +101,21 @@ def start(self) -> None: port = self.config_service.get_port() host = self.config_service.get_host() self.log_service.debug(f"Starting eel port={port} mode={mode} host={host}") - eel.start("index.html", size=(1024, 768), port=port, mode=mode, host=host) + eel.start( + "index.html", + size=(1024, 768), + port=port, + mode=mode, + host=host, + close_callback=self.on_close, + ) + self.log_service.info("Exiting main app normally") except Exception as e: self.log_service.error("error in main app start", e) traceback.print_exc() raise e + + def on_close(self, _page: str, _open_sockets: list) -> None: + self.log_service.info( + "To close the egui app ensure the browser tab is closed and hit Ctrl+C" + ) diff --git a/src/electionguard_gui/web/components/guardian/guardian-home-component.js b/src/electionguard_gui/web/components/guardian/guardian-home-component.js index 5b226d7a..54a5e457 100644 --- a/src/electionguard_gui/web/components/guardian/guardian-home-component.js +++ b/src/electionguard_gui/web/components/guardian/guardian-home-component.js @@ -2,6 +2,8 @@ import KeyCeremonyList from "../shared/key-ceremony-list-component.js"; import DecryptionList from "./decryption-list-component.js"; import Spinner from "../shared/spinner-component.js"; +const sleepResumeInterval = 2000; + export default { components: { KeyCeremonyList, @@ -13,9 +15,21 @@ export default { loading: true, decryptions: [], keyCeremonies: [], + lastAwakeTime: new Date().getTime(), }; }, methods: { + refresh: async function () { + this.loading = true; + try { + this.decryptions = []; + this.keyCeremonies = []; + await this.refreshDecryptions(); + await this.refreshKeyCeremonies(); + } finally { + this.loading = false; + } + }, keyCeremoniesChanged: async function () { await this.refreshKeyCeremonies(); }, @@ -38,8 +52,17 @@ export default { console.error(result.error); } }, + sleepResumeChecker: function () { + var currentTime = new Date().getTime(); + if (currentTime > this.lastAwakeTime + sleepResumeInterval * 2) { + console.log("system appears to have returned from sleep, refreshing"); + document.location.reload(true); + } + this.lastAwakeTime = currentTime; + }, }, async mounted() { + setInterval(this.sleepResumeChecker, sleepResumeInterval); eel.expose(this.keyCeremoniesChanged, "key_ceremonies_changed"); eel.expose(this.decryptionsChanged, "decryptions_changed"); console.log("begin watching for key ceremonies"); @@ -51,10 +74,18 @@ export default { unmounted() { console.log("stop watching key ceremonies"); eel.stop_watching_db_collections(); + clearInterval(this.sleepResumeChecker); }, template: /*html*/ `