fix(05-review): CR-01+WR-01 prune sentReminders after each scan and mark-sent after dispatch
This commit is contained in:
@@ -130,8 +130,6 @@ export async function runReminderCheck(now = new Date()): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
const key = `${uid}:${minuteBucket}`
|
const key = `${uid}:${minuteBucket}`
|
||||||
if (sentReminders.has(key)) continue
|
if (sentReminders.has(key)) continue
|
||||||
// Mark sent BEFORE dispatching to prevent re-entry on concurrent ticks
|
|
||||||
sentReminders.add(key)
|
|
||||||
|
|
||||||
const dateStr = yyyyMmDd(event.dtstartUtc)
|
const dateStr = yyyyMmDd(event.dtstartUtc)
|
||||||
const notification: NotificationPayload = {
|
const notification: NotificationPayload = {
|
||||||
@@ -157,6 +155,11 @@ export async function runReminderCheck(now = new Date()): Promise<void> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WR-01: mark sent AFTER all dispatches have been attempted. Pre-marking before
|
||||||
|
// dispatch prevents retry in the same bucket when dispatchPush throws — at-least-once
|
||||||
|
// delivery requires not pre-marking the key.
|
||||||
|
sentReminders.add(key)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Per-event error isolation (T-05-18): one bad event never aborts remaining events.
|
// Per-event error isolation (T-05-18): one bad event never aborts remaining events.
|
||||||
console.error(
|
console.error(
|
||||||
@@ -165,6 +168,18 @@ export async function runReminderCheck(now = new Date()): Promise<void> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CR-01: Prune stale entries from sentReminders to prevent unbounded growth.
|
||||||
|
// Entries for the previous minute bucket and older are no longer needed — the
|
||||||
|
// dedup window is (uid, minuteBucket), and the current minute has now been
|
||||||
|
// processed. Keep only the current bucket; discard everything older.
|
||||||
|
const staleBucket = minuteBucket - 1
|
||||||
|
for (const key of sentReminders) {
|
||||||
|
const colonIdx = key.lastIndexOf(':')
|
||||||
|
if (colonIdx !== -1 && Number(key.slice(colonIdx + 1)) < staleBucket) {
|
||||||
|
sentReminders.delete(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Scheduler ─────────────────────────────────────────────────────────────────
|
// ── Scheduler ─────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user