Skip to content

Commit a4735e4

Browse files
tjbckcode-quad3
andcommitted
refac
Co-Authored-By: Syed Mustafa Quadri <175467872+code-quad3@users.noreply.github.com>
1 parent 6c8dfd8 commit a4735e4

2 files changed

Lines changed: 15 additions & 13 deletions

File tree

backend/open_webui/models/calendar.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -695,35 +695,34 @@ async def get_upcoming_events(
695695
self,
696696
now_ns: int,
697697
default_lookahead_ns: int,
698+
grace_ns: int = 0,
698699
db: Optional[AsyncSession] = None,
699700
) -> list[tuple[CalendarEventModel, Optional[str]]]:
700701
"""Events starting between now and now + lookahead, for alert processing.
701702
702703
Per-event lookahead is read from meta.alert_minutes (falls back to
703704
default_lookahead_ns). Returns (event, user_timezone) pairs.
705+
706+
*grace_ns* widens the SQL lower bound so that events whose start_at
707+
is up to *grace_ns* nanoseconds in the past are still fetched. This
708+
ensures "At time of event" alerts (alert_minutes=0) are not missed
709+
when the scheduler polls a few seconds after the event's exact start
710+
time.
704711
"""
705712
from open_webui.models.users import User as UserRow
706-
from open_webui.utils.automations import SCHEDULER_POLL_INTERVAL
707713

708714
# Use the maximum possible lookahead (60 min) to cast a wide net;
709715
# per-event filtering happens in Python after fetching.
710716
max_lookahead_ns = max(default_lookahead_ns, 60 * 60 * 1_000_000_000)
711717
upper = now_ns + max_lookahead_ns
712718

713-
# Grace window: allow events whose start_at is up to one poll cycle
714-
# in the past. This ensures "At time of event" alerts (alert_minutes=0)
715-
# are not missed when the scheduler polls a few seconds after the
716-
# event's exact start time.
717-
grace_ns = (SCHEDULER_POLL_INTERVAL + 5) * 1_000_000_000
718-
lower = now_ns - grace_ns
719-
720719
async with get_async_db_context(db) as db:
721720
result = await db.execute(
722721
select(CalendarEvent, UserRow.timezone)
723722
.outerjoin(UserRow, UserRow.id == CalendarEvent.user_id)
724723
.filter(
725724
CalendarEvent.is_cancelled == False,
726-
CalendarEvent.start_at >= lower,
725+
CalendarEvent.start_at >= now_ns - grace_ns,
727726
CalendarEvent.start_at <= upper,
728727
)
729728
)
@@ -741,9 +740,7 @@ async def get_upcoming_events(
741740
if alert_minutes < 0:
742741
# alert_minutes < 0 means "no alert"
743742
continue
744-
# For "at time of event" (0 minutes), use the grace window
745-
# so events that just started are still captured.
746-
event_lookahead_ns = max(alert_minutes * 60 * 1_000_000_000, grace_ns)
743+
event_lookahead_ns = alert_minutes * 60 * 1_000_000_000
747744
else:
748745
event_lookahead_ns = default_lookahead_ns
749746

backend/open_webui/utils/automations.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,14 @@ async def _check_calendar_alerts(app) -> None:
500500

501501
now_ns = int(time.time_ns())
502502
default_lookahead_ns = CALENDAR_ALERT_LOOKAHEAD_MINUTES * 60 * 1_000_000_000
503+
# Grace window covers one poll cycle + jitter so "At time of event"
504+
# alerts (alert_minutes=0) are not missed.
505+
grace_ns = (SCHEDULER_POLL_INTERVAL + 5) * 1_000_000_000
503506

504507
async with get_async_db() as db:
505-
upcoming = await CalendarEvents.get_upcoming_events(now_ns, default_lookahead_ns, db=db)
508+
upcoming = await CalendarEvents.get_upcoming_events(
509+
now_ns, default_lookahead_ns, grace_ns=grace_ns, db=db
510+
)
506511

507512
if not upcoming:
508513
return

0 commit comments

Comments
 (0)