Retry Smarty coordinator update after transient failure (#182309)

This commit is contained in:
Marco
2026-09-15 16:56:44 +02:00
committed by GitHub
parent 362fa725e6
commit 02e719292d
2 changed files with 49 additions and 2 deletions
@@ -45,4 +45,7 @@ class SmartyCoordinator(DataUpdateCoordinator[None]):
async def _async_update_data(self) -> None:
"""Fetch data from Smarty."""
if not await self.hass.async_add_executor_job(self.client.update):
raise UpdateFailed("Failed to update Smarty data")
raise UpdateFailed(
"Failed to update Smarty data",
retry_after=2 if self.last_update_success else None,
)
+45 -1
View File
@@ -1,7 +1,9 @@
"""Tests for the Smarty sensor platform."""
from datetime import timedelta
from unittest.mock import AsyncMock, patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy.assertion import SnapshotAssertion
@@ -11,7 +13,7 @@ from homeassistant.helpers import entity_registry as er
from . import setup_integration
from tests.common import MockConfigEntry, snapshot_platform
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
@pytest.mark.freeze_time("2023-10-21")
@@ -27,3 +29,45 @@ async def test_all_entities(
await setup_integration(hass, mock_config_entry)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
async def test_retry_after_failure(
hass: HomeAssistant,
mock_smarty: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test retrying once after a transient update failure."""
with patch("homeassistant.components.smarty.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, mock_config_entry)
mock_smarty.update.reset_mock()
mock_smarty.update.side_effect = [False, False, True]
# First scheduled update fails after the normal 30-second interval.
freezer.tick(timedelta(seconds=30))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert mock_smarty.update.call_count == 1
# The coordinator retries after 2 seconds.
freezer.tick(timedelta(seconds=2))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert mock_smarty.update.call_count == 2
# A second consecutive failure falls back to the normal interval.
freezer.tick(timedelta(seconds=2))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert mock_smarty.update.call_count == 2
# The next update occurs after the normal 30-second interval.
freezer.tick(timedelta(seconds=28))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert mock_smarty.update.call_count == 3