From 3ce17f2146e5e49e7bd38829eccac18eb64ac959 Mon Sep 17 00:00:00 2001 From: Mitja Horvat Date: Thu, 3 Sep 2026 21:47:24 +0200 Subject: [PATCH] perf: parallelize the TURN OFF button via shared _shutdown_devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit shutdown_all() was the only remaining sequential shutdown path (TV, then Gabi, then Gaja — 10+s with SSH timeouts). It now uses the same parallel _shutdown_devices() as the budget tick, which gained a {dev_id: result} return value so the button response keeps per-device details and registry ordering. Per-device failures are isolated instead of being silently swallowed. --- devices.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/devices.py b/devices.py index 898aba3..91dd940 100644 --- a/devices.py +++ b/devices.py @@ -278,12 +278,25 @@ def curfew_status() -> dict: } -def _shutdown_devices(device_ids: list[str]): - """Shut down a list of devices in parallel.""" +def _shutdown_devices(device_ids: list[str]) -> dict[str, dict | None]: + """Shut down a list of devices in parallel. + + Returns {dev_id: turnoff result or None on failure}. + """ + results: dict[str, dict | None] = {} if not device_ids: - return + return results with ThreadPoolExecutor(max_workers=len(device_ids)) as executor: - list(executor.submit(DEVICES[dev_id]["turnoff"]) for dev_id in device_ids) + futures = { + executor.submit(DEVICES[dev_id]["turnoff"]): dev_id + for dev_id in device_ids + } + for future, dev_id in futures.items(): + try: + results[dev_id] = future.result() + except Exception: + results[dev_id] = None + return results # ── Budget timer (runs every 10s in background) ────────────────────── @@ -415,10 +428,14 @@ def stop_timer(): # ── Orchestrator ────────────────────────────────────────────────────── def shutdown_all() -> list[dict]: - """Indiscriminately turn off all devices. Returns ordered list of action dicts.""" + """Indiscriminately turn off all devices in parallel. + + Returns ordered list of action dicts (registry order). + """ + results = _shutdown_devices(list(DEVICES)) actions = [] for dev_id, dev_info in DEVICES.items(): - result = dev_info["turnoff"]() + result = results.get(dev_id) if result: budget_minutes = _budget_to_minutes(_get_budget(dev_id)) actions.append({