mirror of
https://github.com/home-assistant/core.git
synced 2026-10-06 22:38:02 -04:00
Perform sync when device list changes in Alexa Devices (#183478)
This commit is contained in:
@@ -61,7 +61,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: AmazonConfigEntry) -> bo
|
||||
for sync_call in (
|
||||
coordinator.sync_todo_list_items,
|
||||
coordinator.sync_history_state,
|
||||
coordinator.sync_media_state,
|
||||
):
|
||||
await _async_initial_sync(sync_call)
|
||||
|
||||
|
||||
@@ -216,10 +216,16 @@ class AmazonDevicesCoordinator(DataUpdateCoordinator[dict[str, AmazonDevice]]):
|
||||
) from err
|
||||
else:
|
||||
current_devices = set(data.keys())
|
||||
device_list_changed = current_devices != self.previous_devices
|
||||
if stale_devices := self.previous_devices - current_devices:
|
||||
await self._async_remove_device_stale(stale_devices)
|
||||
self.previous_devices = current_devices
|
||||
|
||||
# sync data on first refresh and after the device list changes
|
||||
# self.data is None only on the first refresh
|
||||
if self.data is None or device_list_changed:
|
||||
await self._async_sync_on_device_list_change()
|
||||
|
||||
current_routines = {
|
||||
f"{slugify(self.config_entry.unique_id)}-{slugify(routine)}"
|
||||
for routine in self.api.routines
|
||||
@@ -238,6 +244,18 @@ class AmazonDevicesCoordinator(DataUpdateCoordinator[dict[str, AmazonDevice]]):
|
||||
|
||||
return data
|
||||
|
||||
async def _async_sync_on_device_list_change(self) -> None:
|
||||
"""Sync per-device state on first refresh and after the device list changes."""
|
||||
for sync_call in (self.sync_media_state,):
|
||||
try:
|
||||
await sync_call()
|
||||
except ConfigEntryNotReady as err:
|
||||
LOGGER.warning(
|
||||
"Sync failed for %s: %s. Data may be missing or incomplete until updates are pushed by Amazon",
|
||||
sync_call.__name__,
|
||||
err,
|
||||
)
|
||||
|
||||
async def _async_remove_device_stale(
|
||||
self,
|
||||
stale_devices: set[str],
|
||||
|
||||
@@ -213,3 +213,71 @@ async def test_sync_media_state_auth_failed(
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert mock_config_entry.state is expected_state
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"error",
|
||||
[
|
||||
pytest.param(
|
||||
CannotConnect("429 - Too Many Requests"),
|
||||
id="http_429_too_many_requests",
|
||||
),
|
||||
pytest.param(
|
||||
CannotRetrieveData("503 - Service Unavailable"),
|
||||
id="http_503_service_unavailable",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_media_state_sync_failure_logged_on_first_refresh(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
mock_amazon_devices_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
error: Exception,
|
||||
) -> None:
|
||||
"""Test a failing media sync on first refresh is logged but does not block setup."""
|
||||
mock_amazon_devices_client.sync_media_state.side_effect = error
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert "Sync failed for sync_media_state:" in caplog.text
|
||||
assert str(error) in caplog.text
|
||||
assert (
|
||||
"Data may be missing or incomplete until updates are pushed by Amazon"
|
||||
in caplog.text
|
||||
)
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_media_state_sync_on_device_list_change(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
mock_amazon_devices_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test media state is resynced when a device is added."""
|
||||
mock_amazon_devices_client.get_devices_data.return_value = {
|
||||
TEST_DEVICE_1_SN: TEST_DEVICE_1,
|
||||
}
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
mock_amazon_devices_client.sync_media_state.assert_awaited_once()
|
||||
|
||||
mock_amazon_devices_client.get_devices_data.return_value = {
|
||||
TEST_DEVICE_1_SN: TEST_DEVICE_1,
|
||||
TEST_DEVICE_2_SN: TEST_DEVICE_2,
|
||||
}
|
||||
|
||||
freezer.tick(SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_amazon_devices_client.sync_media_state.call_count == 2
|
||||
|
||||
freezer.tick(SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Device list unchanged: no additional resync
|
||||
assert mock_amazon_devices_client.sync_media_state.call_count == 2
|
||||
|
||||
@@ -43,11 +43,6 @@ def _fail_history_state(client: AsyncMock, error: Exception) -> None:
|
||||
client.sync_history_state.side_effect = error
|
||||
|
||||
|
||||
def _fail_media_state(client: AsyncMock, error: Exception) -> None:
|
||||
"""Make the media state sync fail."""
|
||||
client.sync_media_state.side_effect = error
|
||||
|
||||
|
||||
async def test_device_info(
|
||||
hass: HomeAssistant,
|
||||
snapshot: SnapshotAssertion,
|
||||
@@ -252,7 +247,6 @@ async def test_http2_stop_processing_called_on_shutdown(
|
||||
[
|
||||
(_fail_todo_list_items, "sync_todo_list_items"),
|
||||
(_fail_history_state, "sync_history_state"),
|
||||
(_fail_media_state, "sync_media_state"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
Reference in New Issue
Block a user