Improve Huawei LTE timeouting/stalling request behavior (#31710)
* Suppress data get timeout exceptions for 30s after notify attempts At least SMS send failures may put the API in a state where it times out some (but not all) data get operations for some time, e.g. 25s. Closes https://github.com/home-assistant/home-assistant/issues/30827 * Do not pile up duplicate data requests Do not add another request for a piece of data for which a previous request is still in progress. For example failing SMS sends are known to stall some (but not all) requests for some time, and firing up more is not going to help.pull/31735/head
parent
54eb740ff6
commit
d1b0ab736d
|
@ -5,6 +5,7 @@ from datetime import timedelta
|
|||
from functools import partial
|
||||
import ipaddress
|
||||
import logging
|
||||
import time
|
||||
from typing import Any, Callable, Dict, List, Set, Tuple
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
@ -65,6 +66,7 @@ from .const import (
|
|||
KEY_MONITORING_STATUS,
|
||||
KEY_MONITORING_TRAFFIC_STATISTICS,
|
||||
KEY_WLAN_HOST_LIST,
|
||||
NOTIFY_SUPPRESS_TIMEOUT,
|
||||
SERVICE_CLEAR_TRAFFIC_STATISTICS,
|
||||
SERVICE_REBOOT,
|
||||
SERVICE_RESUME_INTEGRATION,
|
||||
|
@ -138,9 +140,11 @@ class Router:
|
|||
init=False,
|
||||
factory=lambda: defaultdict(set, ((x, {"initial_scan"}) for x in ALL_KEYS)),
|
||||
)
|
||||
inflight_gets: Set[str] = attr.ib(init=False, factory=set)
|
||||
unload_handlers: List[CALLBACK_TYPE] = attr.ib(init=False, factory=list)
|
||||
client: Client
|
||||
suspended = attr.ib(init=False, default=False)
|
||||
notify_last_attempt: float = attr.ib(init=False, default=-1)
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
"""Set up internal state on init."""
|
||||
|
@ -167,6 +171,10 @@ class Router:
|
|||
def _get_data(self, key: str, func: Callable[[None], Any]) -> None:
|
||||
if not self.subscriptions.get(key):
|
||||
return
|
||||
if key in self.inflight_gets:
|
||||
_LOGGER.debug("Skipping already inflight get for %s", key)
|
||||
return
|
||||
self.inflight_gets.add(key)
|
||||
_LOGGER.debug("Getting %s for subscribers %s", key, self.subscriptions[key])
|
||||
try:
|
||||
self.data[key] = func()
|
||||
|
@ -189,7 +197,21 @@ class Router:
|
|||
"%s requires authorization, excluding from future updates", key
|
||||
)
|
||||
self.subscriptions.pop(key)
|
||||
except Timeout:
|
||||
grace_left = (
|
||||
self.notify_last_attempt - time.monotonic() + NOTIFY_SUPPRESS_TIMEOUT
|
||||
)
|
||||
if grace_left > 0:
|
||||
_LOGGER.debug(
|
||||
"%s timed out, %.1fs notify timeout suppress grace remaining",
|
||||
key,
|
||||
grace_left,
|
||||
exc_info=True,
|
||||
)
|
||||
else:
|
||||
raise
|
||||
finally:
|
||||
self.inflight_gets.discard(key)
|
||||
_LOGGER.debug("%s=%s", key, self.data.get(key))
|
||||
|
||||
def update(self) -> None:
|
||||
|
|
|
@ -12,6 +12,7 @@ UNIT_BYTES = "B"
|
|||
UNIT_SECONDS = "s"
|
||||
|
||||
CONNECTION_TIMEOUT = 10
|
||||
NOTIFY_SUPPRESS_TIMEOUT = 30
|
||||
|
||||
SERVICE_CLEAR_TRAFFIC_STATISTICS = "clear_traffic_statistics"
|
||||
SERVICE_REBOOT = "reboot"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""Support for Huawei LTE router notifications."""
|
||||
|
||||
import logging
|
||||
import time
|
||||
from typing import Any, List
|
||||
|
||||
import attr
|
||||
|
@ -57,3 +58,5 @@ class HuaweiLteSmsNotificationService(BaseNotificationService):
|
|||
_LOGGER.debug("Sent to %s: %s", targets, resp)
|
||||
except ResponseErrorException as ex:
|
||||
_LOGGER.error("Could not send to %s: %s", targets, ex)
|
||||
finally:
|
||||
self.router.notify_last_attempt = time.monotonic()
|
||||
|
|
Loading…
Reference in New Issue