mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
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
This commit is contained in:
parent
13001faf51
commit
973fee9fe1
@ -47,8 +47,6 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
type HomeConnectConfigEntry = ConfigEntry[HomeConnectCoordinator]
|
type HomeConnectConfigEntry = ConfigEntry[HomeConnectCoordinator]
|
||||||
|
|
||||||
EVENT_STREAM_RECONNECT_DELAY = 30
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, kw_only=True)
|
@dataclass(frozen=True, kw_only=True)
|
||||||
class HomeConnectApplianceData:
|
class HomeConnectApplianceData:
|
||||||
@ -157,9 +155,11 @@ class HomeConnectCoordinator(
|
|||||||
|
|
||||||
async def _event_listener(self) -> None:
|
async def _event_listener(self) -> None:
|
||||||
"""Match event with listener for event type."""
|
"""Match event with listener for event type."""
|
||||||
|
retry_time = 10
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
async for event_message in self.client.stream_all_events():
|
async for event_message in self.client.stream_all_events():
|
||||||
|
retry_time = 10
|
||||||
event_message_ha_id = event_message.ha_id
|
event_message_ha_id = event_message.ha_id
|
||||||
match event_message.type:
|
match event_message.type:
|
||||||
case EventType.STATUS:
|
case EventType.STATUS:
|
||||||
@ -256,20 +256,18 @@ class HomeConnectCoordinator(
|
|||||||
except (EventStreamInterruptedError, HomeConnectRequestError) as error:
|
except (EventStreamInterruptedError, HomeConnectRequestError) as error:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Non-breaking error (%s) while listening for events,"
|
"Non-breaking error (%s) while listening for events,"
|
||||||
" continuing in 30 seconds",
|
" continuing in %s seconds",
|
||||||
type(error).__name__,
|
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:
|
except HomeConnectApiError as error:
|
||||||
_LOGGER.error("Error while listening for events: %s", error)
|
_LOGGER.error("Error while listening for events: %s", error)
|
||||||
self.hass.config_entries.async_schedule_reload(
|
self.hass.config_entries.async_schedule_reload(
|
||||||
self.config_entry.entry_id
|
self.config_entry.entry_id
|
||||||
)
|
)
|
||||||
break
|
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
|
@callback
|
||||||
def _call_event_listener(self, event_message: EventMessage) -> None:
|
def _call_event_listener(self, event_message: EventMessage) -> None:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Test for Home Connect coordinator."""
|
"""Test for Home Connect coordinator."""
|
||||||
|
|
||||||
from collections.abc import Awaitable, Callable
|
from collections.abc import Awaitable, Callable
|
||||||
|
from datetime import timedelta
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
@ -12,8 +13,6 @@ from aiohomeconnect.model import (
|
|||||||
EventKey,
|
EventKey,
|
||||||
EventMessage,
|
EventMessage,
|
||||||
EventType,
|
EventType,
|
||||||
Status,
|
|
||||||
StatusKey,
|
|
||||||
)
|
)
|
||||||
from aiohomeconnect.model.error import (
|
from aiohomeconnect.model.error import (
|
||||||
EventStreamInterruptedError,
|
EventStreamInterruptedError,
|
||||||
@ -24,7 +23,6 @@ from aiohomeconnect.model.error import (
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.home_connect.const import (
|
from homeassistant.components.home_connect.const import (
|
||||||
BSH_DOOR_STATE_LOCKED,
|
|
||||||
BSH_DOOR_STATE_OPEN,
|
BSH_DOOR_STATE_OPEN,
|
||||||
BSH_EVENT_PRESENT_STATE_PRESENT,
|
BSH_EVENT_PRESENT_STATE_PRESENT,
|
||||||
BSH_POWER_OFF,
|
BSH_POWER_OFF,
|
||||||
@ -38,8 +36,9 @@ from homeassistant.core import (
|
|||||||
callback,
|
callback,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers import entity_registry as er
|
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
|
@pytest.fixture
|
||||||
@ -286,9 +285,6 @@ async def test_event_listener_error(
|
|||||||
(
|
(
|
||||||
"entity_id",
|
"entity_id",
|
||||||
"initial_state",
|
"initial_state",
|
||||||
"status_key",
|
|
||||||
"status_value",
|
|
||||||
"after_refresh_expected_state",
|
|
||||||
"event_key",
|
"event_key",
|
||||||
"event_value",
|
"event_value",
|
||||||
"after_event_expected_state",
|
"after_event_expected_state",
|
||||||
@ -297,24 +293,15 @@ async def test_event_listener_error(
|
|||||||
(
|
(
|
||||||
"sensor.washer_door",
|
"sensor.washer_door",
|
||||||
"closed",
|
"closed",
|
||||||
StatusKey.BSH_COMMON_DOOR_STATE,
|
|
||||||
BSH_DOOR_STATE_LOCKED,
|
|
||||||
"locked",
|
|
||||||
EventKey.BSH_COMMON_STATUS_DOOR_STATE,
|
EventKey.BSH_COMMON_STATUS_DOOR_STATE,
|
||||||
BSH_DOOR_STATE_OPEN,
|
BSH_DOOR_STATE_OPEN,
|
||||||
"open",
|
"open",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@patch(
|
|
||||||
"homeassistant.components.home_connect.coordinator.EVENT_STREAM_RECONNECT_DELAY", 0
|
|
||||||
)
|
|
||||||
async def test_event_listener_resilience(
|
async def test_event_listener_resilience(
|
||||||
entity_id: str,
|
entity_id: str,
|
||||||
initial_state: str,
|
initial_state: str,
|
||||||
status_key: StatusKey,
|
|
||||||
status_value: Any,
|
|
||||||
after_refresh_expected_state: str,
|
|
||||||
event_key: EventKey,
|
event_key: EventKey,
|
||||||
event_value: Any,
|
event_value: Any,
|
||||||
after_event_expected_state: str,
|
after_event_expected_state: str,
|
||||||
@ -345,16 +332,13 @@ async def test_event_listener_resilience(
|
|||||||
|
|
||||||
assert hass.states.is_state(entity_id, initial_state)
|
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()
|
await hass.async_block_till_done()
|
||||||
future.set_exception(exception)
|
future.set_exception(exception)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert client.stream_all_events.call_count == 2
|
assert client.stream_all_events.call_count == 2
|
||||||
assert hass.states.is_state(entity_id, after_refresh_expected_state)
|
|
||||||
|
|
||||||
await client.add_events(
|
await client.add_events(
|
||||||
[
|
[
|
||||||
|
Loading…
x
Reference in New Issue
Block a user