Shutdown coordinator on entry unload (#91748)
Co-authored-by: J. Nick Koston <nick@koston.org>pull/91760/merge
parent
a37a87e972
commit
79ad9a3646
|
@ -64,7 +64,10 @@ class Debouncer(Generic[_R_co]):
|
||||||
async def async_call(self) -> None:
|
async def async_call(self) -> None:
|
||||||
"""Call the function."""
|
"""Call the function."""
|
||||||
if self._shutdown_requested:
|
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
|
assert self._job is not None
|
||||||
|
|
||||||
if self._timer_task:
|
if self._timer_task:
|
||||||
|
|
|
@ -114,6 +114,9 @@ class DataUpdateCoordinator(BaseDataUpdateCoordinatorProtocol, Generic[_T]):
|
||||||
|
|
||||||
self._debounced_refresh = request_refresh_debouncer
|
self._debounced_refresh = request_refresh_debouncer
|
||||||
|
|
||||||
|
if self.config_entry:
|
||||||
|
self.config_entry.async_on_unload(self.async_shutdown)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_listener(
|
def async_add_listener(
|
||||||
self, update_callback: CALLBACK_TYPE, context: Any = None
|
self, update_callback: CALLBACK_TYPE, context: Any = None
|
||||||
|
|
|
@ -182,7 +182,7 @@ async def test_immediate_works_with_function_swapped(hass: HomeAssistant) -> Non
|
||||||
assert debouncer._job.target == debouncer.function
|
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."""
|
"""Test shutdown."""
|
||||||
calls = []
|
calls = []
|
||||||
future = asyncio.Future()
|
future = asyncio.Future()
|
||||||
|
@ -208,5 +208,9 @@ async def test_shutdown(hass: HomeAssistant) -> None:
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert debouncer._timer_task is None
|
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()
|
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
|
||||||
|
|
|
@ -153,6 +153,39 @@ async def test_shutdown(
|
||||||
assert updates == [2]
|
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(
|
async def test_update_context(
|
||||||
crd: update_coordinator.DataUpdateCoordinator[int],
|
crd: update_coordinator.DataUpdateCoordinator[int],
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
Loading…
Reference in New Issue