Delete refresh after a non-breaking error at event stream at Home Connect (#139740)

* Delete refresh after non-breaking error

And improve how many time does it take to retry to open stream

* Update tests
pull/136458/merge
J. Diego Rodríguez Royo 2025-03-04 11:07:44 +01:00 committed by GitHub
parent 13001faf51
commit 973fee9fe1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 28 deletions

View File

@ -47,8 +47,6 @@ _LOGGER = logging.getLogger(__name__)
type HomeConnectConfigEntry = ConfigEntry[HomeConnectCoordinator]
EVENT_STREAM_RECONNECT_DELAY = 30
@dataclass(frozen=True, kw_only=True)
class HomeConnectApplianceData:
@ -157,9 +155,11 @@ class HomeConnectCoordinator(
async def _event_listener(self) -> None:
"""Match event with listener for event type."""
retry_time = 10
while True:
try:
async for event_message in self.client.stream_all_events():
retry_time = 10
event_message_ha_id = event_message.ha_id
match event_message.type:
case EventType.STATUS:
@ -256,20 +256,18 @@ class HomeConnectCoordinator(
except (EventStreamInterruptedError, HomeConnectRequestError) as error:
_LOGGER.debug(
"Non-breaking error (%s) while listening for events,"
" continuing in 30 seconds",
" continuing in %s seconds",
type(error).__name__,
retry_time,
)
await asyncio.sleep(EVENT_STREAM_RECONNECT_DELAY)
await asyncio.sleep(retry_time)
retry_time = min(retry_time * 2, 3600)
except HomeConnectApiError as error:
_LOGGER.error("Error while listening for events: %s", error)
self.hass.config_entries.async_schedule_reload(
self.config_entry.entry_id
)
break
# if there was a non-breaking error, we continue listening
# but we need to refresh the data to get the possible changes
# that happened while the event stream was interrupted
await self.async_refresh()
@callback
def _call_event_listener(self, event_message: EventMessage) -> None:

View File

@ -1,6 +1,7 @@
"""Test for Home Connect coordinator."""
from collections.abc import Awaitable, Callable
from datetime import timedelta
from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch
@ -12,8 +13,6 @@ from aiohomeconnect.model import (
EventKey,
EventMessage,
EventType,
Status,
StatusKey,
)
from aiohomeconnect.model.error import (
EventStreamInterruptedError,
@ -24,7 +23,6 @@ from aiohomeconnect.model.error import (
import pytest
from homeassistant.components.home_connect.const import (
BSH_DOOR_STATE_LOCKED,
BSH_DOOR_STATE_OPEN,
BSH_EVENT_PRESENT_STATE_PRESENT,
BSH_POWER_OFF,
@ -38,8 +36,9 @@ from homeassistant.core import (
callback,
)
from homeassistant.helpers import entity_registry as er
from homeassistant.util import dt as dt_util
from tests.common import MockConfigEntry
from tests.common import MockConfigEntry, async_fire_time_changed
@pytest.fixture
@ -286,9 +285,6 @@ async def test_event_listener_error(
(
"entity_id",
"initial_state",
"status_key",
"status_value",
"after_refresh_expected_state",
"event_key",
"event_value",
"after_event_expected_state",
@ -297,24 +293,15 @@ async def test_event_listener_error(
(
"sensor.washer_door",
"closed",
StatusKey.BSH_COMMON_DOOR_STATE,
BSH_DOOR_STATE_LOCKED,
"locked",
EventKey.BSH_COMMON_STATUS_DOOR_STATE,
BSH_DOOR_STATE_OPEN,
"open",
),
],
)
@patch(
"homeassistant.components.home_connect.coordinator.EVENT_STREAM_RECONNECT_DELAY", 0
)
async def test_event_listener_resilience(
entity_id: str,
initial_state: str,
status_key: StatusKey,
status_value: Any,
after_refresh_expected_state: str,
event_key: EventKey,
event_value: Any,
after_event_expected_state: str,
@ -345,16 +332,13 @@ async def test_event_listener_resilience(
assert hass.states.is_state(entity_id, initial_state)
client.get_status.return_value = ArrayOfStatus(
[Status(key=status_key, raw_key=status_key.value, value=status_value)],
)
await hass.async_block_till_done()
future.set_exception(exception)
await hass.async_block_till_done()
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
await hass.async_block_till_done()
assert client.stream_all_events.call_count == 2
assert hass.states.is_state(entity_id, after_refresh_expected_state)
await client.add_events(
[