From c0ebf291013cebf6b13e6a333fbaacb477eabaaa Mon Sep 17 00:00:00 2001 From: Gary Miguel Date: Fri, 24 Jul 2026 08:17:03 -0700 Subject: [PATCH] fix: add timeout to mqtt connect to avoid indefinite hang connect_future.result was awaited with no timeout, so an unreachable or half-open connection to the Hatch cloud blocked the executor thread and the calling coroutine forever. Follows the same approach as the MQTT_TIMEOUT added to ShadowClientSubscriberMixin in #60. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01KUv54T1tjc6TJYCsUXyPE2 --- src/hatch_rest_api/util_bootstrap.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/hatch_rest_api/util_bootstrap.py b/src/hatch_rest_api/util_bootstrap.py index 51b83ba..93eddda 100644 --- a/src/hatch_rest_api/util_bootstrap.py +++ b/src/hatch_rest_api/util_bootstrap.py @@ -32,6 +32,11 @@ _LOGGER = logging.getLogger(__name__) +# Seconds to wait for the MQTT connection to establish before giving up. +# Prevents thread pool workers from blocking indefinitely when the Hatch +# cloud is unreachable in ways that don't fail fast (e.g. hung TCP). +MQTT_CONNECT_TIMEOUT = 30 + io.init_logging(io.LogLevel.NoLogs, "stderr") @@ -93,7 +98,9 @@ async def get_rest_devices( ) try: connect_future = await loop.run_in_executor(None, mqtt_connection.connect) - await loop.run_in_executor(None, connect_future.result) + await loop.run_in_executor( + None, partial(connect_future.result, MQTT_CONNECT_TIMEOUT) + ) _LOGGER.debug("mqtt connection connected") except Exception as e: _LOGGER.error(f"MQTT connection failed with exception {e}")