mirror of
https://github.com/home-assistant/core.git
synced 2025-04-26 10:17:51 +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:
|
async def _fetch_events(self, last_endtime: datetime.datetime) -> None:
|
||||||
"""Update the set of eligible events."""
|
"""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)
|
_LOGGER.debug("Fetching events between %s, %s", last_endtime, end_time)
|
||||||
events = await self._entity.async_get_events(self._hass, 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:
|
async def _handle_calendar_event(self, now: datetime.datetime) -> None:
|
||||||
"""Handle calendar event."""
|
"""Handle calendar event."""
|
||||||
_LOGGER.debug("Calendar event @ %s", now)
|
_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:
|
while self._events and self._events[0][0] <= now:
|
||||||
(_fire_time, event) = self._events.pop(0)
|
(_fire_time, event) = self._events.pop(0)
|
||||||
_LOGGER.debug("Event: %s", event)
|
_LOGGER.debug("Event: %s", event)
|
||||||
@ -134,12 +139,13 @@ class CalendarEventListener:
|
|||||||
self._job,
|
self._job,
|
||||||
{"trigger": {**self._trigger_data, "calendar_event": event.as_dict()}},
|
{"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:
|
async def _handle_refresh(self, now: datetime.datetime) -> None:
|
||||||
"""Handle core config update."""
|
"""Handle core config update."""
|
||||||
_LOGGER.debug("Refresh events @ %s", now)
|
_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()
|
self._clear_event_listener()
|
||||||
await self._fetch_events(now)
|
await self._fetch_events(now)
|
||||||
self._listen_next_calendar_event()
|
self._listen_next_calendar_event()
|
||||||
|
@ -481,3 +481,27 @@ async def test_event_payload(hass, calls, fake_schedule):
|
|||||||
"calendar_event": event_data,
|
"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