fix: calendar check-in digest drops events 7-8 days out (#1249)
* fix: close 1-day gap in calendar digest windows (events ~7-8 days out) * test: calendar digest windows are contiguous and cover 7-8 day events
This commit is contained in:
@@ -203,6 +203,20 @@ RETIRED_HOUSEKEEPING_ACTIONS = frozenset({
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def _digest_windows(now):
|
||||||
|
"""(label, start, end) buckets for the calendar check-in digest.
|
||||||
|
|
||||||
|
The windows are contiguous so no event is dropped between buckets — an
|
||||||
|
earlier version started the 30-day window at now+8d while the week window
|
||||||
|
ended at now+7d, so events ~7-8 days out fell into no bucket.
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
("today_tomorrow", now, now + timedelta(days=2)),
|
||||||
|
("this_week", now + timedelta(days=2), now + timedelta(days=7)),
|
||||||
|
("next_30_days", now + timedelta(days=7), now + timedelta(days=30)),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TaskScheduler:
|
class TaskScheduler:
|
||||||
def __init__(self, session_manager):
|
def __init__(self, session_manager):
|
||||||
self._session_manager = session_manager
|
self._session_manager = session_manager
|
||||||
@@ -1082,11 +1096,7 @@ class TaskScheduler:
|
|||||||
from core.database import SessionLocal as _SL, CalendarEvent as _CE
|
from core.database import SessionLocal as _SL, CalendarEvent as _CE
|
||||||
_db = _SL()
|
_db = _SL()
|
||||||
try:
|
try:
|
||||||
for label, start, end in [
|
for label, start, end in _digest_windows(now):
|
||||||
("today_tomorrow", now, now + timedelta(days=2)),
|
|
||||||
("this_week", now + timedelta(days=2), now + timedelta(days=7)),
|
|
||||||
("next_30_days", now + timedelta(days=8), now + timedelta(days=30)),
|
|
||||||
]:
|
|
||||||
# Strip timezone for naive DB comparison
|
# Strip timezone for naive DB comparison
|
||||||
_s = start.replace(tzinfo=None) if start.tzinfo else start
|
_s = start.replace(tzinfo=None) if start.tzinfo else start
|
||||||
_e = end.replace(tzinfo=None) if end.tzinfo else end
|
_e = end.replace(tzinfo=None) if end.tzinfo else end
|
||||||
|
|||||||
22
tests/test_digest_windows.py
Normal file
22
tests/test_digest_windows.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
"""Tests for the calendar check-in digest windows (src/task_scheduler.py)."""
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
from src.task_scheduler import _digest_windows
|
||||||
|
|
||||||
|
|
||||||
|
def test_windows_are_contiguous_with_no_gap():
|
||||||
|
now = datetime(2026, 6, 2, 9, 0, 0)
|
||||||
|
windows = _digest_windows(now)
|
||||||
|
# Each window starts exactly where the previous ended — no gap between
|
||||||
|
# buckets (the old code jumped from now+7d to now+8d, dropping events).
|
||||||
|
for (prev, cur) in zip(windows, windows[1:]):
|
||||||
|
assert cur[1] == prev[2]
|
||||||
|
assert windows[0][1] == now
|
||||||
|
assert windows[-1][2] == now + timedelta(days=30)
|
||||||
|
|
||||||
|
|
||||||
|
def test_event_seven_and_a_half_days_out_is_covered():
|
||||||
|
now = datetime(2026, 6, 2, 9, 0, 0)
|
||||||
|
event = now + timedelta(days=7, hours=12) # fell in the old 7-8 day gap
|
||||||
|
buckets = [label for label, start, end in _digest_windows(now) if start <= event <= end]
|
||||||
|
assert buckets, "event ~7.5 days out should land in a digest window"
|
||||||
Reference in New Issue
Block a user