Reload ZHA only a single time when the connection is lost multiple times (#107963)

* Reload only a single time when the connection is lost multiple times

* Ignore when reset task finishes, allow only one reset per `ZHAGateway`
This commit is contained in:
puddly 2024-01-13 16:32:25 -05:00 committed by Franck Nijhof
parent 20b88e30f5
commit 8a3eb149b7
No known key found for this signature in database
GPG key ID: D62583BA8AB11CA3
2 changed files with 43 additions and 2 deletions

View file

@ -142,7 +142,9 @@ class ZHAGateway:
self._log_relay_handler = LogRelayHandler(hass, self)
self.config_entry = config_entry
self._unsubs: list[Callable[[], None]] = []
self.shutting_down = False
self._reload_task: asyncio.Task | None = None
def get_application_controller_data(self) -> tuple[ControllerApplication, dict]:
"""Get an uninitialized instance of a zigpy `ControllerApplication`."""
@ -231,12 +233,17 @@ class ZHAGateway:
def connection_lost(self, exc: Exception) -> None:
"""Handle connection lost event."""
_LOGGER.debug("Connection to the radio was lost: %r", exc)
if self.shutting_down:
return
_LOGGER.debug("Connection to the radio was lost: %r", exc)
# Ensure we do not queue up multiple resets
if self._reload_task is not None:
_LOGGER.debug("Ignoring reset, one is already running")
return
self.hass.async_create_task(
self._reload_task = self.hass.async_create_task(
self.hass.config_entries.async_reload(self.config_entry.entry_id)
)
@ -760,6 +767,10 @@ class ZHAGateway:
async def shutdown(self) -> None:
"""Stop ZHA Controller Application."""
if self.shutting_down:
_LOGGER.debug("Ignoring duplicate shutdown event")
return
_LOGGER.debug("Shutting down ZHA ControllerApplication")
self.shutting_down = True

View file

@ -291,3 +291,33 @@ async def test_gateway_force_multi_pan_channel(
_, config = zha_gateway.get_application_controller_data()
assert config["network"]["channel"] == expected_channel
async def test_single_reload_on_multiple_connection_loss(
hass: HomeAssistant,
zigpy_app_controller: ControllerApplication,
config_entry: MockConfigEntry,
):
"""Test that we only reload once when we lose the connection multiple times."""
config_entry.add_to_hass(hass)
zha_gateway = ZHAGateway(hass, {}, config_entry)
with patch(
"bellows.zigbee.application.ControllerApplication.new",
return_value=zigpy_app_controller,
):
await zha_gateway.async_initialize()
with patch.object(
hass.config_entries, "async_reload", wraps=hass.config_entries.async_reload
) as mock_reload:
zha_gateway.connection_lost(RuntimeError())
zha_gateway.connection_lost(RuntimeError())
zha_gateway.connection_lost(RuntimeError())
zha_gateway.connection_lost(RuntimeError())
zha_gateway.connection_lost(RuntimeError())
assert len(mock_reload.mock_calls) == 1
await hass.async_block_till_done()