Shutdown coordinator on entry unload (#91748)

Co-authored-by: J. Nick Koston <nick@koston.org>
pull/91760/merge
epenet 2023-04-21 10:07:31 +02:00 committed by GitHub
parent a37a87e972
commit 79ad9a3646
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 4 deletions

View File

@ -64,7 +64,10 @@ class Debouncer(Generic[_R_co]):
async def async_call(self) -> None:
"""Call the function."""
if self._shutdown_requested:
raise RuntimeError("Debouncer has been shutdown.")
self.logger.warning(
"Debouncer call ignored as shutdown has been requested."
)
return
assert self._job is not None
if self._timer_task:

View File

@ -114,6 +114,9 @@ class DataUpdateCoordinator(BaseDataUpdateCoordinatorProtocol, Generic[_T]):
self._debounced_refresh = request_refresh_debouncer
if self.config_entry:
self.config_entry.async_on_unload(self.async_shutdown)
@callback
def async_add_listener(
self, update_callback: CALLBACK_TYPE, context: Any = None

View File

@ -182,7 +182,7 @@ async def test_immediate_works_with_function_swapped(hass: HomeAssistant) -> Non
assert debouncer._job.target == debouncer.function
async def test_shutdown(hass: HomeAssistant) -> None:
async def test_shutdown(hass: HomeAssistant, caplog: pytest.LogCaptureFixture) -> None:
"""Test shutdown."""
calls = []
future = asyncio.Future()
@ -208,5 +208,9 @@ async def test_shutdown(hass: HomeAssistant) -> None:
assert len(calls) == 1
assert debouncer._timer_task is None
with pytest.raises(RuntimeError, match="Debouncer has been shutdown"):
assert "Debouncer call ignored as shutdown has been requested." not in caplog.text
await debouncer.async_call()
assert "Debouncer call ignored as shutdown has been requested." in caplog.text
assert len(calls) == 1
assert debouncer._timer_task is None

View File

@ -153,6 +153,39 @@ async def test_shutdown(
assert updates == [2]
async def test_shutdown_on_entry_unload(
hass: HomeAssistant,
crd: update_coordinator.DataUpdateCoordinator[int],
) -> None:
"""Test shutdown is requested on entry unload."""
entry = MockConfigEntry()
config_entries.current_entry.set(entry)
calls = 0
async def _refresh() -> int:
nonlocal calls
calls += 1
return calls
crd = update_coordinator.DataUpdateCoordinator[int](
hass,
_LOGGER,
name="test",
update_method=_refresh,
update_interval=DEFAULT_UPDATE_INTERVAL,
)
crd.async_add_listener(lambda: None)
assert crd._unsub_refresh is not None
assert not crd._shutdown_requested
await entry._async_process_on_unload(hass)
assert crd._shutdown_requested
assert crd._unsub_refresh is None
async def test_update_context(
crd: update_coordinator.DataUpdateCoordinator[int],
) -> None: