mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 01:38:02 +00:00
Fix boundary case in calednar trigger (#70467)
Update calendar trigger scan logic to add a one second boundary due to the exclusive search. Add a test that reproduced the issue.
This commit is contained in:
parent
965665213f
commit
dc7e3a6df6
@ -81,7 +81,8 @@ class CalendarEventListener:
|
||||
|
||||
async def _fetch_events(self, last_endtime: datetime.datetime) -> None:
|
||||
"""Update the set of eligible events."""
|
||||
end_time = last_endtime + UPDATE_INTERVAL
|
||||
# Event time ranges are exclusive so the end time is expanded by 1sec
|
||||
end_time = last_endtime + UPDATE_INTERVAL + datetime.timedelta(seconds=1)
|
||||
_LOGGER.debug("Fetching events between %s, %s", last_endtime, end_time)
|
||||
events = await self._entity.async_get_events(self._hass, last_endtime, end_time)
|
||||
|
||||
@ -125,8 +126,12 @@ class CalendarEventListener:
|
||||
async def _handle_calendar_event(self, now: datetime.datetime) -> None:
|
||||
"""Handle calendar event."""
|
||||
_LOGGER.debug("Calendar event @ %s", now)
|
||||
self._dispatch_events(now)
|
||||
self._clear_event_listener()
|
||||
self._listen_next_calendar_event()
|
||||
|
||||
# Consume all events that are eligible to fire
|
||||
def _dispatch_events(self, now: datetime.datetime) -> None:
|
||||
"""Dispatch all events that are eligible to fire."""
|
||||
while self._events and self._events[0][0] <= now:
|
||||
(_fire_time, event) = self._events.pop(0)
|
||||
_LOGGER.debug("Event: %s", event)
|
||||
@ -134,12 +139,13 @@ class CalendarEventListener:
|
||||
self._job,
|
||||
{"trigger": {**self._trigger_data, "calendar_event": event.as_dict()}},
|
||||
)
|
||||
self._clear_event_listener()
|
||||
self._listen_next_calendar_event()
|
||||
|
||||
async def _handle_refresh(self, now: datetime.datetime) -> None:
|
||||
"""Handle core config update."""
|
||||
_LOGGER.debug("Refresh events @ %s", now)
|
||||
# Dispatch any eligible events in the boundary case where refresh
|
||||
# fires before the calendar event.
|
||||
self._dispatch_events(now)
|
||||
self._clear_event_listener()
|
||||
await self._fetch_events(now)
|
||||
self._listen_next_calendar_event()
|
||||
|
@ -481,3 +481,27 @@ async def test_event_payload(hass, calls, fake_schedule):
|
||||
"calendar_event": event_data,
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
async def test_trigger_timestamp_window_edge(hass, calls, fake_schedule, freezer):
|
||||
"""Test that events in the edge of a scan are included."""
|
||||
freezer.move_to("2022-04-19 11:00:00+00:00")
|
||||
# Exactly at a TEST_UPDATE_INTERVAL boundary the start time,
|
||||
# making this excluded from the first window.
|
||||
event_data = fake_schedule.create_event(
|
||||
start=datetime.datetime.fromisoformat("2022-04-19 11:14:00+00:00"),
|
||||
end=datetime.datetime.fromisoformat("2022-04-19 11:30:00+00:00"),
|
||||
)
|
||||
await create_automation(hass, EVENT_START)
|
||||
assert len(calls()) == 0
|
||||
|
||||
await fake_schedule.fire_until(
|
||||
datetime.datetime.fromisoformat("2022-04-19 11:20:00+00:00")
|
||||
)
|
||||
assert calls() == [
|
||||
{
|
||||
"platform": "calendar",
|
||||
"event": EVENT_START,
|
||||
"calendar_event": event_data,
|
||||
}
|
||||
]
|
||||
|
Loading…
x
Reference in New Issue
Block a user