fix: drain stale futures in __get_prop_handler on batch failure (#1723)

When get_props_async raises (cloud timeout, network error, etc.) the
pending futures registered in self._get_prop_list stay unresolved
forever. Subsequent get_prop_async calls with the same (did, siid, piid)
key reuse the dead future via the cache lookup at the top of
get_prop_async, so the integration never recovers from a single batch
failure until Home Assistant is restarted.

This was reproducible whenever the cloud HTTP request hung past the
caller's wait_for timeout: every later poll for that key returned the
same cancelled-but-still-pending future. Property entities driven by
async_update silently stopped updating with no error in the logs.

Wrap the await in try/except and fall through with results=[]. The
existing fallback loop then drains every key still in props_req with
set_result(None), unblocking awaiters and freeing the cache slot so
the next aggregation cycle starts fresh.
This commit is contained in:
Vergil Zhao
2026-09-24 12:17:12 +08:00
committed by GitHub
parent 8a59021445
commit cf2a4bf649

View File

@@ -755,7 +755,18 @@ class MIoTHttpClient:
if not props_buffer:
_LOGGER.error('get prop error, empty request list')
return False
results = await self.get_props_async(props_buffer)
try:
results = await self.get_props_async(props_buffer)
except Exception as err: # pylint: disable=broad-exception-caught
# If the batch request fails (timeout, network error, etc.), the
# pending futures in self._get_prop_list would otherwise stay
# unresolved forever. Subsequent get_prop_async calls with the
# same key reuse the dead future via the cache lookup at the top
# of get_prop_async, so the integration would never recover until
# restart. Fall through with empty results so the loop below
# drains every requested key with set_result(None).
_LOGGER.error('get prop batch failed, %s', err)
results = []
for result in results:
if not all(