test(05): UAT Test 1 PASS — scheduled reminder delivers on real iPhone after node-cron→setInterval + catch-up fixes
Tests 1 & 2 pass (subscribe + scheduled reminder delivery proven on-device). Gap resolved via quick tasks 260610-hbu (catch-up scan) and 260610-i4x (node-cron→setInterval). Tests 3/4/5 still pending (elapsed time / Android / two devices).
This commit is contained in:
@@ -3,7 +3,7 @@ status: testing
|
||||
phase: 05-web-push-notifications
|
||||
source: [05-VERIFICATION.md]
|
||||
started: 2026-06-10T02:46:43Z
|
||||
updated: 2026-06-10T16:25:00Z
|
||||
updated: 2026-06-10T17:14:00Z
|
||||
---
|
||||
|
||||
## Current Test
|
||||
@@ -20,10 +20,9 @@ awaiting: user response
|
||||
### 1. iOS PWA install → push subscription → 15-min reminder receipt
|
||||
expected: After adding FamilySync to the Home Screen on an iOS 16.4+ device and tapping "Enable Notifications", a push notification appears on the lock screen ~15 minutes before a shared Family-calendar timed event starts.
|
||||
why_human: iOS-Safari standalone push delivery cannot be driven by playwright-cli per CLAUDE.md — requires a physical iOS device + Home Screen install.
|
||||
result: issue
|
||||
reported: "Scheduled 15-min reminder did NOT arrive at the window. node-cron logged 'missed execution' at 15:59/16:00/16:01 UTC (exactly the [now+14,now+16] reminder window). A manual scan with injected time found the event and dispatched to the same subscription → Apple 201 → the notification arrived on the iPhone. So delivery works; the scheduled trigger was dropped."
|
||||
severity: major
|
||||
root_cause: "Two factors. (1) node-cron missed the every-minute reminder tick during the window (intermittent — measured setInterval drift was negligible afterward and host/container clocks were in sync, so not sustained clock drift; likely transient tick starvation). (2) DESIGN: reminderScheduler scans only the fixed [now+14,now+16] window keyed to one exact tick, with no catch-up — a single missed/late tick drops the reminder permanently. Dispatch chain (VAPID sign → Apple → SW showNotification on iOS) is proven working."
|
||||
result: pass
|
||||
note: "PASS confirmed on a real iPhone via the SCHEDULED path (no manual trigger). Initially failed; two root causes found and fixed: (1) node-cron 4.2.1 skipped EVERY scheduled execution in the long-running API process ('missed execution' each tick) → replaced node-cron with setInterval in all 3 broker workers (quick 260610-i4x). (2) The reminder scan only checked a fixed [now+14,now+16] window with no catch-up, so a missed/late tick dropped the reminder permanently → added a catch-up window (now, now+16min] + per-uid exactly-once dedup (quick 260610-hbu). After redeploy, a shared-calendar timed event triggered a push reminder on its own (setInterval → catch-up scan → VAPID sign → Apple 201 → SW showNotification on the iPhone). Also required fixing a truncated VAPID private key in .env earlier."
|
||||
fix_commits: ["260610-hbu (catch-up + per-uid dedup)", "260610-i4x (node-cron→setInterval)"]
|
||||
|
||||
### 2. iOS push subscription does not receive NotAllowedError
|
||||
expected: Tapping "Enable Notifications" on iOS in the installed PWA (or the Settings toggle) successfully calls pushManager.subscribe() without throwing NotAllowedError. Both vapidKey and swRegistration are pre-resolved in state before the tap.
|
||||
@@ -50,8 +49,8 @@ result: [pending]
|
||||
## Summary
|
||||
|
||||
total: 5
|
||||
passed: 1
|
||||
issues: 1
|
||||
passed: 2
|
||||
issues: 0
|
||||
pending: 3
|
||||
skipped: 0
|
||||
blocked: 0
|
||||
@@ -65,11 +64,9 @@ blocked: 0
|
||||
## Gaps
|
||||
|
||||
- truth: "A shared-calendar timed event triggers a push reminder ~15 min before start, delivered to subscribed devices"
|
||||
status: failed
|
||||
reason: "Scheduled reminder did not fire. node-cron missed the every-minute tick during the [now+14,now+16] window; the scan has NO catch-up, so the reminder was dropped permanently. Underlying dispatch+delivery verified working (manual trigger → Apple 201 → notification on the iPhone)."
|
||||
status: RESOLVED 2026-06-10
|
||||
reason: "Originally failed (scheduled reminder never fired). Two root causes found + fixed: (a) node-cron 4.2.1 skipped EVERY scheduled execution in the long-running API process → replaced with setInterval in all 3 broker workers (quick 260610-i4x, commit d9efbc1); (b) reminder scan had no catch-up so a missed/late tick dropped the reminder → added catch-up window (now, now+16min] + per-uid exactly-once dedup (quick 260610-hbu, commit 19d92c6). After redeploy, a real shared-calendar event triggered a push on the iPhone via the SCHEDULED path with no manual trigger."
|
||||
severity: major
|
||||
test: 1
|
||||
artifacts: [apps/api/src/broker/reminderScheduler.ts, apps/api/src/index.ts]
|
||||
missing:
|
||||
- "Resilient reminder scan: persist a last-scanned-time watermark and scan [lastScanned, now+16min] each run (keep the (uid, minuteBucket) dedup) so a missed/late cron tick is recovered on the next run instead of being lost."
|
||||
- "Confirm node-cron tick reliability on the real Unraid host (the misses were observed on the WSL2 dev box; need to know if prod is affected)."
|
||||
artifacts: [apps/api/src/broker/reminderScheduler.ts, apps/api/src/broker/poller.ts, apps/api/src/broker/outboxWorker.ts]
|
||||
note: "Side benefit: the node-cron→setInterval fix also restores the CalDAV poller (5-min sync) and outbox drain (15s), which were ALSO being skipped by node-cron in the long-running process."
|
||||
|
||||
Reference in New Issue
Block a user