Add and improve comments about staggering of event listeners (#99058)
parent
8768c39021
commit
3a71e21d6a
|
@ -68,6 +68,10 @@ _ENTITIES_LISTENER = "entities"
|
|||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# Used to spread async_track_utc_time_change listeners and DataUpdateCoordinator
|
||||
# refresh cycles between RANDOM_MICROSECOND_MIN..RANDOM_MICROSECOND_MAX.
|
||||
# The values have been determined experimentally in production testing, background
|
||||
# in PR https://github.com/home-assistant/core/pull/82233
|
||||
RANDOM_MICROSECOND_MIN = 50000
|
||||
RANDOM_MICROSECOND_MAX = 500000
|
||||
|
||||
|
@ -1640,7 +1644,7 @@ def async_track_utc_time_change(
|
|||
matching_seconds = dt_util.parse_time_expression(second, 0, 59)
|
||||
matching_minutes = dt_util.parse_time_expression(minute, 0, 59)
|
||||
matching_hours = dt_util.parse_time_expression(hour, 0, 23)
|
||||
# Avoid aligning all time trackers to the same second
|
||||
# Avoid aligning all time trackers to the same fraction of a second
|
||||
# since it can create a thundering herd problem
|
||||
# https://github.com/home-assistant/core/issues/82231
|
||||
microsecond = randint(RANDOM_MICROSECOND_MIN, RANDOM_MICROSECOND_MAX)
|
||||
|
|
|
@ -59,6 +59,7 @@ from homeassistant.helpers import (
|
|||
entity,
|
||||
entity_platform,
|
||||
entity_registry as er,
|
||||
event,
|
||||
intent,
|
||||
issue_registry as ir,
|
||||
recorder as recorder_helper,
|
||||
|
@ -397,9 +398,10 @@ def async_fire_time_changed(
|
|||
) -> None:
|
||||
"""Fire a time changed event.
|
||||
|
||||
This function will add up to 0.5 seconds to the time to ensure that
|
||||
it accounts for the accidental synchronization avoidance code in repeating
|
||||
listeners.
|
||||
If called within the first 500 ms of a second, time will be bumped to exactly
|
||||
500 ms to match the async_track_utc_time_change event listeners and
|
||||
DataUpdateCoordinator which spreads all updates between 0.05..0.50.
|
||||
Background in PR https://github.com/home-assistant/core/pull/82233
|
||||
|
||||
As asyncio is cooperative, we can't guarantee that the event loop will
|
||||
run an event at the exact time we want. If you need to fire time changed
|
||||
|
@ -410,12 +412,12 @@ def async_fire_time_changed(
|
|||
else:
|
||||
utc_datetime = dt_util.as_utc(datetime_)
|
||||
|
||||
if utc_datetime.microsecond < 500000:
|
||||
if utc_datetime.microsecond < event.RANDOM_MICROSECOND_MAX:
|
||||
# Allow up to 500000 microseconds to be added to the time
|
||||
# to handle update_coordinator's and
|
||||
# async_track_time_interval's
|
||||
# staggering to avoid thundering herd.
|
||||
utc_datetime = utc_datetime.replace(microsecond=500000)
|
||||
utc_datetime = utc_datetime.replace(microsecond=event.RANDOM_MICROSECOND_MAX)
|
||||
|
||||
_async_fire_time_changed(hass, utc_datetime, fire_all)
|
||||
|
||||
|
|
Loading…
Reference in New Issue