mirror of
https://github.com/home-assistant/core.git
synced 2026-09-26 09:23:17 -04:00
Handle unavailable UniFi configuration endpoint (#182574)
This commit is contained in:
@@ -3,10 +3,11 @@
|
||||
from datetime import timedelta
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
from aiounifi import EndpointNotFound
|
||||
from aiounifi.interfaces.api_handlers import APIHandler, ItemEvent
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import LOGGER
|
||||
|
||||
@@ -25,6 +26,8 @@ class UnifiDataUpdateCoordinator[HandlerT: APIHandler](
|
||||
self,
|
||||
hub: UnifiHub,
|
||||
handler: HandlerT,
|
||||
*,
|
||||
disable_polling_on_endpoint_not_found: bool = False,
|
||||
) -> None:
|
||||
"""Initialize coordinator."""
|
||||
supports_websocket = bool(handler.process_messages or handler.remove_messages)
|
||||
@@ -36,6 +39,10 @@ class UnifiDataUpdateCoordinator[HandlerT: APIHandler](
|
||||
update_interval=None if supports_websocket else POLL_INTERVAL,
|
||||
)
|
||||
self._handler = handler
|
||||
self._disable_polling_on_endpoint_not_found = (
|
||||
disable_polling_on_endpoint_not_found
|
||||
)
|
||||
self._endpoint_not_found_logged = False
|
||||
|
||||
hub.config.entry.async_on_unload(handler.subscribe(self._async_handle_update))
|
||||
|
||||
@@ -47,7 +54,20 @@ class UnifiDataUpdateCoordinator[HandlerT: APIHandler](
|
||||
@override
|
||||
async def _async_update_data(self) -> None:
|
||||
"""Update data from the API handler."""
|
||||
await self._handler.update()
|
||||
try:
|
||||
await self._handler.update()
|
||||
except EndpointNotFound as err:
|
||||
if (
|
||||
self._disable_polling_on_endpoint_not_found
|
||||
and not self._endpoint_not_found_logged
|
||||
):
|
||||
self._endpoint_not_found_logged = True
|
||||
self.update_interval = None
|
||||
self.logger.warning(
|
||||
"UniFi %s endpoint is unavailable; disabling polling",
|
||||
type(self._handler).__name__,
|
||||
)
|
||||
raise UpdateFailed(str(err)) from err
|
||||
|
||||
@callback
|
||||
def _async_handle_update(self, event: ItemEvent, obj_id: str) -> None:
|
||||
|
||||
@@ -53,7 +53,9 @@ class UnifiEntityLoader:
|
||||
hub, hub.api.firewall_policies
|
||||
),
|
||||
id(hub.api.object_oriented_network_configs): UnifiDataUpdateCoordinator(
|
||||
hub, hub.api.object_oriented_network_configs
|
||||
hub,
|
||||
hub.api.object_oriented_network_configs,
|
||||
disable_polling_on_endpoint_not_found=True,
|
||||
),
|
||||
id(hub.api.port_forwarding): UnifiDataUpdateCoordinator(
|
||||
hub, hub.api.port_forwarding
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
import aiounifi
|
||||
from aiounifi import EndpointNotFound
|
||||
from aiounifi.interfaces.api_handlers import ItemEvent
|
||||
from aiounifi.models.message import MessageKey
|
||||
import pytest
|
||||
@@ -122,6 +123,49 @@ async def test_polling_coordinator_refreshes_after_interval(
|
||||
assert mock_update.call_count >= 1
|
||||
|
||||
|
||||
async def test_endpoint_not_found_disables_object_oriented_network_config_polling(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
config_entry_setup: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Ensure an unavailable optional endpoint stops polling after one warning."""
|
||||
loader = config_entry_setup.runtime_data.entity_loader
|
||||
api = config_entry_setup.runtime_data.api
|
||||
coordinator = loader.get_data_update_coordinator(
|
||||
api.object_oriented_network_configs
|
||||
)
|
||||
traffic_rules_coordinator = loader.get_data_update_coordinator(api.traffic_rules)
|
||||
|
||||
with patch.object(
|
||||
coordinator.handler,
|
||||
"update",
|
||||
side_effect=EndpointNotFound("endpoint not found"),
|
||||
) as mock_update:
|
||||
await coordinator.async_refresh()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert coordinator.update_interval is None
|
||||
assert coordinator.last_update_success is False
|
||||
assert mock_update.call_count == 1
|
||||
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + POLL_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_update.call_count == 1
|
||||
|
||||
await coordinator.async_refresh()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_update.call_count == 2
|
||||
assert traffic_rules_coordinator.update_interval == POLL_INTERVAL
|
||||
assert (
|
||||
caplog.text.count(
|
||||
"UniFi ObjectOrientedNetworkConfigs endpoint is unavailable; disabling polling"
|
||||
)
|
||||
== 1
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"object_oriented_network_config_payload",
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user