From fc931ac449cfe1efdc3f27b14c5c60502efa3576 Mon Sep 17 00:00:00 2001 From: Allen Porter Date: Mon, 20 May 2024 22:59:11 -0700 Subject: [PATCH] Stop the nest subscriber on Home Assistant stop (#117830) --- homeassistant/components/nest/__init__.py | 14 +++++++++++--- tests/components/nest/common.py | 4 +++- tests/components/nest/test_init.py | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/nest/__init__.py b/homeassistant/components/nest/__init__.py index 43862bb5106..96231390119 100644 --- a/homeassistant/components/nest/__init__.py +++ b/homeassistant/components/nest/__init__.py @@ -34,9 +34,10 @@ from homeassistant.const import ( CONF_MONITORED_CONDITIONS, CONF_SENSORS, CONF_STRUCTURE, + EVENT_HOMEASSISTANT_STOP, Platform, ) -from homeassistant.core import HomeAssistant +from homeassistant.core import Event, HomeAssistant, callback from homeassistant.exceptions import ( ConfigEntryAuthFailed, ConfigEntryNotReady, @@ -196,8 +197,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_config_reload() -> None: await hass.config_entries.async_reload(entry.entry_id) - callback = SignalUpdateCallback(hass, async_config_reload) - subscriber.set_update_callback(callback.async_handle_event) + update_callback = SignalUpdateCallback(hass, async_config_reload) + subscriber.set_update_callback(update_callback.async_handle_event) try: await subscriber.start_async() except AuthException as err: @@ -218,6 +219,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: subscriber.stop_async() raise ConfigEntryNotReady(f"Device manager error: {err!s}") from err + @callback + def on_hass_stop(_: Event) -> None: + """Close connection when hass stops.""" + subscriber.stop_async() + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop) + hass.data[DOMAIN][entry.entry_id] = { DATA_SUBSCRIBER: subscriber, DATA_DEVICE_MANAGER: device_manager, diff --git a/tests/components/nest/common.py b/tests/components/nest/common.py index 01aac79af02..08e3a4d1ddc 100644 --- a/tests/components/nest/common.py +++ b/tests/components/nest/common.py @@ -90,6 +90,8 @@ TEST_CONFIG_ENTRY_LEGACY = NestTestConfig( class FakeSubscriber(GoogleNestSubscriber): """Fake subscriber that supplies a FakeDeviceManager.""" + stop_calls = 0 + def __init__(self): """Initialize Fake Subscriber.""" self._device_manager = DeviceManager() @@ -121,7 +123,7 @@ class FakeSubscriber(GoogleNestSubscriber): def stop_async(self): """No-op to stop the subscriber.""" - return None + self.stop_calls += 1 async def async_receive_event(self, event_message: EventMessage): """Simulate a received pubsub message, invoked by tests.""" diff --git a/tests/components/nest/test_init.py b/tests/components/nest/test_init.py index e77ba3bb7e1..879cedbdd43 100644 --- a/tests/components/nest/test_init.py +++ b/tests/components/nest/test_init.py @@ -32,6 +32,7 @@ from .common import ( TEST_CONFIG_LEGACY, TEST_CONFIGFLOW_APP_CREDS, FakeSubscriber, + PlatformSetup, YieldFixture, ) @@ -241,6 +242,23 @@ async def test_remove_entry( assert not entries +async def test_home_assistant_stop( + hass: HomeAssistant, + setup_platform: PlatformSetup, + subscriber: FakeSubscriber, +) -> None: + """Test successful subscriber shutdown when HomeAssistant stops.""" + await setup_platform() + + entries = hass.config_entries.async_entries(DOMAIN) + assert len(entries) == 1 + entry = entries[0] + assert entry.state is ConfigEntryState.LOADED + + await hass.async_stop() + assert subscriber.stop_calls == 1 + + async def test_remove_entry_delete_subscriber_failure( hass: HomeAssistant, setup_base_platform ) -> None: