mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Adjust Hue retry logic to changes in the aiohue library (#62665)
This commit is contained in:
parent
aa9746808e
commit
8e759bb267
@ -3,13 +3,12 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from http import HTTPStatus
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aiohttp import client_exceptions
|
from aiohttp import client_exceptions
|
||||||
from aiohue import HueBridgeV1, HueBridgeV2, LinkButtonNotPressed, Unauthorized
|
from aiohue import HueBridgeV1, HueBridgeV2, LinkButtonNotPressed, Unauthorized
|
||||||
from aiohue.errors import AiohueException
|
from aiohue.errors import AiohueException, BridgeBusy
|
||||||
import async_timeout
|
import async_timeout
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
@ -44,9 +43,6 @@ class HueBridge:
|
|||||||
self.config_entry = config_entry
|
self.config_entry = config_entry
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.authorized = False
|
self.authorized = False
|
||||||
self.parallel_updates_semaphore = asyncio.Semaphore(
|
|
||||||
3 if self.api_version == 1 else 10
|
|
||||||
)
|
|
||||||
# Jobs to be executed when API is reset.
|
# Jobs to be executed when API is reset.
|
||||||
self.reset_jobs: list[core.CALLBACK_TYPE] = []
|
self.reset_jobs: list[core.CALLBACK_TYPE] = []
|
||||||
self.sensor_manager: SensorManager | None = None
|
self.sensor_manager: SensorManager | None = None
|
||||||
@ -89,6 +85,7 @@ class HueBridge:
|
|||||||
client_exceptions.ClientOSError,
|
client_exceptions.ClientOSError,
|
||||||
client_exceptions.ServerDisconnectedError,
|
client_exceptions.ServerDisconnectedError,
|
||||||
client_exceptions.ContentTypeError,
|
client_exceptions.ContentTypeError,
|
||||||
|
BridgeBusy,
|
||||||
) as err:
|
) as err:
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"Error connecting to the Hue bridge at {self.host}"
|
f"Error connecting to the Hue bridge at {self.host}"
|
||||||
@ -121,50 +118,19 @@ class HueBridge:
|
|||||||
async def async_request_call(
|
async def async_request_call(
|
||||||
self, task: Callable, *args, allowed_errors: list[str] | None = None, **kwargs
|
self, task: Callable, *args, allowed_errors: list[str] | None = None, **kwargs
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""Limit parallel requests to Hue hub.
|
"""Send request to the Hue bridge, optionally omitting error(s)."""
|
||||||
|
|
||||||
The Hue hub can only handle a certain amount of parallel requests, total.
|
|
||||||
Although we limit our parallel requests, we still will run into issues because
|
|
||||||
other products are hitting up Hue.
|
|
||||||
|
|
||||||
ClientOSError means hub closed the socket on us.
|
|
||||||
ContentResponseError means hub raised an error.
|
|
||||||
Since we don't make bad requests, this is on them.
|
|
||||||
"""
|
|
||||||
max_tries = 5
|
|
||||||
async with self.parallel_updates_semaphore:
|
|
||||||
for tries in range(max_tries):
|
|
||||||
try:
|
try:
|
||||||
return await task(*args, **kwargs)
|
return await task(*args, **kwargs)
|
||||||
except AiohueException as err:
|
except AiohueException as err:
|
||||||
# The new V2 api is a bit more fanatic with throwing errors
|
# The (new) Hue api can be a bit fanatic with throwing errors
|
||||||
# some of which we accept in certain conditions
|
# some of which we accept in certain conditions
|
||||||
# handle that here. Note that these errors are strings and do not have
|
# handle that here. Note that these errors are strings and do not have
|
||||||
# an identifier or something.
|
# an identifier or something.
|
||||||
if allowed_errors is not None and str(err) in allowed_errors:
|
if allowed_errors is not None and str(err) in allowed_errors:
|
||||||
# log only
|
# log only
|
||||||
self.logger.debug(
|
self.logger.debug("Ignored error/warning from Hue API: %s", str(err))
|
||||||
"Ignored error/warning from Hue API: %s", str(err)
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
raise err
|
raise err
|
||||||
except (
|
|
||||||
client_exceptions.ClientOSError,
|
|
||||||
client_exceptions.ClientResponseError,
|
|
||||||
client_exceptions.ServerDisconnectedError,
|
|
||||||
) as err:
|
|
||||||
if tries == max_tries:
|
|
||||||
self.logger.error("Request failed %s times, giving up", tries)
|
|
||||||
raise
|
|
||||||
|
|
||||||
# We only retry if it's a server error. So raise on all 4XX errors.
|
|
||||||
if (
|
|
||||||
isinstance(err, client_exceptions.ClientResponseError)
|
|
||||||
and err.status < HTTPStatus.INTERNAL_SERVER_ERROR
|
|
||||||
):
|
|
||||||
raise
|
|
||||||
|
|
||||||
await asyncio.sleep(HUB_BUSY_SLEEP * tries)
|
|
||||||
|
|
||||||
async def async_reset(self) -> bool:
|
async def async_reset(self) -> bool:
|
||||||
"""Reset this bridge to default state.
|
"""Reset this bridge to default state.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user