mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Reduce overhead for google calendar state updates (#108133)
This commit is contained in:
parent
d9f1450ee6
commit
fa63719161
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ from gcal_sync.model import AccessRole, DateOrDatetime, Event
|
|||||||
from gcal_sync.store import ScopedCalendarStore
|
from gcal_sync.store import ScopedCalendarStore
|
||||||
from gcal_sync.sync import CalendarEventSyncManager
|
from gcal_sync.sync import CalendarEventSyncManager
|
||||||
from gcal_sync.timeline import Timeline
|
from gcal_sync.timeline import Timeline
|
||||||
|
from ical.iter import SortableItemValue
|
||||||
|
|
||||||
from homeassistant.components.calendar import (
|
from homeassistant.components.calendar import (
|
||||||
CREATE_EVENT_SCHEMA,
|
CREATE_EVENT_SCHEMA,
|
||||||
@ -76,6 +78,9 @@ from .const import (
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
|
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
|
||||||
|
# Maximum number of upcoming events to consider for state changes between
|
||||||
|
# coordinator updates.
|
||||||
|
MAX_UPCOMING_EVENTS = 20
|
||||||
|
|
||||||
# Avoid syncing super old data on initial syncs. Note that old but active
|
# Avoid syncing super old data on initial syncs. Note that old but active
|
||||||
# recurring events are still included.
|
# recurring events are still included.
|
||||||
@ -244,6 +249,22 @@ async def async_setup_entry(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _truncate_timeline(timeline: Timeline, max_events: int) -> Timeline:
|
||||||
|
"""Truncate the timeline to a maximum number of events.
|
||||||
|
|
||||||
|
This is used to avoid repeated expansion of recurring events during
|
||||||
|
state machine updates.
|
||||||
|
"""
|
||||||
|
upcoming = timeline.active_after(dt_util.now())
|
||||||
|
truncated = list(itertools.islice(upcoming, max_events))
|
||||||
|
return Timeline(
|
||||||
|
[
|
||||||
|
SortableItemValue(event.timespan_of(dt_util.DEFAULT_TIME_ZONE), event)
|
||||||
|
for event in truncated
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
|
class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
|
||||||
"""Coordinator for calendar RPC calls that use an efficient sync."""
|
"""Coordinator for calendar RPC calls that use an efficient sync."""
|
||||||
|
|
||||||
@ -263,6 +284,7 @@ class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
|
|||||||
update_interval=MIN_TIME_BETWEEN_UPDATES,
|
update_interval=MIN_TIME_BETWEEN_UPDATES,
|
||||||
)
|
)
|
||||||
self.sync = sync
|
self.sync = sync
|
||||||
|
self._upcoming_timeline: Timeline | None = None
|
||||||
|
|
||||||
async def _async_update_data(self) -> Timeline:
|
async def _async_update_data(self) -> Timeline:
|
||||||
"""Fetch data from API endpoint."""
|
"""Fetch data from API endpoint."""
|
||||||
@ -271,9 +293,11 @@ class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
|
|||||||
except ApiException as err:
|
except ApiException as err:
|
||||||
raise UpdateFailed(f"Error communicating with API: {err}") from err
|
raise UpdateFailed(f"Error communicating with API: {err}") from err
|
||||||
|
|
||||||
return await self.sync.store_service.async_get_timeline(
|
timeline = await self.sync.store_service.async_get_timeline(
|
||||||
dt_util.DEFAULT_TIME_ZONE
|
dt_util.DEFAULT_TIME_ZONE
|
||||||
)
|
)
|
||||||
|
self._upcoming_timeline = _truncate_timeline(timeline, MAX_UPCOMING_EVENTS)
|
||||||
|
return timeline
|
||||||
|
|
||||||
async def async_get_events(
|
async def async_get_events(
|
||||||
self, start_date: datetime, end_date: datetime
|
self, start_date: datetime, end_date: datetime
|
||||||
@ -291,8 +315,8 @@ class CalendarSyncUpdateCoordinator(DataUpdateCoordinator[Timeline]):
|
|||||||
@property
|
@property
|
||||||
def upcoming(self) -> Iterable[Event] | None:
|
def upcoming(self) -> Iterable[Event] | None:
|
||||||
"""Return upcoming events if any."""
|
"""Return upcoming events if any."""
|
||||||
if self.data:
|
if self._upcoming_timeline:
|
||||||
return self.data.active_after(dt_util.now())
|
return self._upcoming_timeline.active_after(dt_util.now())
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/calendar.google",
|
"documentation": "https://www.home-assistant.io/integrations/calendar.google",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["googleapiclient"],
|
"loggers": ["googleapiclient"],
|
||||||
"requirements": ["gcal-sync==6.0.3", "oauth2client==4.1.3"]
|
"requirements": ["gcal-sync==6.0.3", "oauth2client==4.1.3", "ical==6.1.1"]
|
||||||
}
|
}
|
||||||
|
@ -1088,6 +1088,7 @@ ibeacon-ble==1.0.1
|
|||||||
# homeassistant.components.watson_iot
|
# homeassistant.components.watson_iot
|
||||||
ibmiotf==0.3.4
|
ibmiotf==0.3.4
|
||||||
|
|
||||||
|
# homeassistant.components.google
|
||||||
# homeassistant.components.local_calendar
|
# homeassistant.components.local_calendar
|
||||||
# homeassistant.components.local_todo
|
# homeassistant.components.local_todo
|
||||||
ical==6.1.1
|
ical==6.1.1
|
||||||
|
@ -872,6 +872,7 @@ iaqualink==0.5.0
|
|||||||
# homeassistant.components.ibeacon
|
# homeassistant.components.ibeacon
|
||||||
ibeacon-ble==1.0.1
|
ibeacon-ble==1.0.1
|
||||||
|
|
||||||
|
# homeassistant.components.google
|
||||||
# homeassistant.components.local_calendar
|
# homeassistant.components.local_calendar
|
||||||
# homeassistant.components.local_todo
|
# homeassistant.components.local_todo
|
||||||
ical==6.1.1
|
ical==6.1.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user