Add and improve comments about staggering of event listeners (#99058)

This commit is contained in:
Erik Montnemery 2023-08-25 19:47:13 +02:00 committed by GitHub
parent 8768c39021
commit 3a71e21d6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 6 deletions

View File

@ -68,6 +68,10 @@ _ENTITIES_LISTENER = "entities"
_LOGGER = logging.getLogger(__name__) _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_MIN = 50000
RANDOM_MICROSECOND_MAX = 500000 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_seconds = dt_util.parse_time_expression(second, 0, 59)
matching_minutes = dt_util.parse_time_expression(minute, 0, 59) matching_minutes = dt_util.parse_time_expression(minute, 0, 59)
matching_hours = dt_util.parse_time_expression(hour, 0, 23) 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 # since it can create a thundering herd problem
# https://github.com/home-assistant/core/issues/82231 # https://github.com/home-assistant/core/issues/82231
microsecond = randint(RANDOM_MICROSECOND_MIN, RANDOM_MICROSECOND_MAX) microsecond = randint(RANDOM_MICROSECOND_MIN, RANDOM_MICROSECOND_MAX)

View File

@ -59,6 +59,7 @@ from homeassistant.helpers import (
entity, entity,
entity_platform, entity_platform,
entity_registry as er, entity_registry as er,
event,
intent, intent,
issue_registry as ir, issue_registry as ir,
recorder as recorder_helper, recorder as recorder_helper,
@ -397,9 +398,10 @@ def async_fire_time_changed(
) -> None: ) -> None:
"""Fire a time changed event. """Fire a time changed event.
This function will add up to 0.5 seconds to the time to ensure that If called within the first 500 ms of a second, time will be bumped to exactly
it accounts for the accidental synchronization avoidance code in repeating 500 ms to match the async_track_utc_time_change event listeners and
listeners. 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 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 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: else:
utc_datetime = dt_util.as_utc(datetime_) 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 # Allow up to 500000 microseconds to be added to the time
# to handle update_coordinator's and # to handle update_coordinator's and
# async_track_time_interval's # async_track_time_interval's
# staggering to avoid thundering herd. # 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) _async_fire_time_changed(hass, utc_datetime, fire_all)