""" Background status checker — daemon thread that pings servers periodically. """ import threading import time from typing import TYPE_CHECKING if TYPE_CHECKING: from core.server_store import ServerStore from core.ssh_client import SSHClientWrapper class StatusChecker: def __init__(self, store: "ServerStore", interval: int = 60): self.store = store self.interval = interval self._running = False self._thread: threading.Thread | None = None self._gui_callback = None # set by GUI for thread-safe updates def start(self): if self._running: return self._running = True self._thread = threading.Thread(target=self._loop, daemon=True) self._thread.start() def stop(self): self._running = False def set_gui_callback(self, callback): """Set callback for thread-safe GUI updates.""" self._gui_callback = callback def check_one(self, server: dict) -> bool: """Check single server. Returns True if online.""" key_path = self.store.get_ssh_key_path() wrapper = SSHClientWrapper(server, key_path) return wrapper.check_connection() def check_all_now(self): """Run a full check cycle immediately (in background thread).""" threading.Thread(target=self._check_cycle, daemon=True).start() def _loop(self): while self._running: self._check_cycle() for _ in range(self.interval * 10): if not self._running: return time.sleep(0.1) def _check_cycle(self): servers = self.store.get_all() for server in servers: if not self._running: return alias = server["alias"] server_type = server.get("type", "ssh") if server_type != "ssh": self.store.set_status(alias, "unknown") continue online = self.check_one(server) self.store.set_status(alias, "online" if online else "offline") if self._gui_callback: try: self._gui_callback() except Exception: pass