fix(calendar): fed slots stay fed across a restart

The reminder source skipped an already-fed slot only while the slot
sat in the dispatcher's pending inbox; a claw restart drained that
inbox, and every future lead of the same occurrence re-fed — a
reminder fired two or three times per calendar event. The source
keeps its own fed-slot ledger in the calendar store now (keyed by
calendar, occurrence, and lead), records each slot right after a
successful ingest, and prunes rows whose occurrence is an hour past
every lead, so a pruned row can never resurrect a reminder. The
store-backed source's ledger survives a restart; the static-list
constructor keeps an in-memory one for the process lifetime, said so
in the docs that previously claimed dedup was someone else's problem.
Store failures surface loudly (a silently lost row is a re-fired
reminder); the prune warns and continues. Offline tests cover the
once-only rule, the restart via a tempdir reopen, and the prune.
This commit is contained in:
vhaudiquet committed 2026-11-05 19:06:41 +01:00
1 parent dad99c7664
commit 5a8be19b4c
5 files changed
+371 -40

No files matched your search

@@ -42,6 +42,9 @@ time = { version = "0.3", default-features = false, features = [
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "sync", "time"] }
# In-process HTTP mocks for offline tests
wiremock = "0.6"
# File-backed stores in offline tests (the fed-slot ledger's restart
# behavior)
tempfile = "3"
[lints]
workspace = true