feat(05-07): implement eventChangeDispatcher + syncCalendar diff/title/onChanges

- Create eventChangeDispatcher.ts: dispatchEventChange + isMeaningfulChange
- D-04: description-only edits are silent; meaningful fields = title/dtstartUtc/dtstartDate/allDay/location
- D-03: actor excluded via ne() + application-level filter; all subs filtered by userId != actorUserId
- D-13: reads only push_subscriptions from MariaDB — no tsdav/Fastmail I/O
- syncCalendar: add optional onChanges callback; populate title from VEVENT SUMMARY on every upsert
- syncCalendar: pre-upsert SELECT to detect add vs update; track changedFields; prune emits deletes
- poller: pass onChanges with actor=cred.userId (external changes from other member)
- outboxWorker.triggerTargetedResync: pass onChanges with actor=userId (this-member writes)
- All 4 eventChangeDispatcher tests + 14 sync tests GREEN
This commit is contained in:
Lucas Berger
2026-06-09 22:03:52 -04:00
parent 4ef6333201
commit 30e9de13f9
4 changed files with 310 additions and 2 deletions
+13 -1
View File
@@ -34,6 +34,7 @@ import { syncCalendar } from './sync.js'
import { createCalendarEvent, updateCalendarEvent, deleteCalendarEvent } from './write.js'
import { buildVeventString, extractRruleString, RRULE_PRESETS } from './vevent.js'
import type { FastmailClient } from './client.js'
import { dispatchEventChange } from '../lib/eventChangeDispatcher.js'
// ── Constants (D-07) ────────────────────────────────────────────────────────
@@ -168,7 +169,18 @@ async function triggerTargetedResync(
return
}
await syncCalendar(client, davCal, userId)
// NOTIF-03: pass onChanges so this-member writes push to the other member.
// actor = userId (the member who wrote via the outbox — D-03).
await syncCalendar(client, davCal, userId, (changes) => {
for (const change of changes) {
dispatchEventChange(change, userId).catch((err: unknown) => {
console.error(
'[outboxWorker] dispatchEventChange error:',
err instanceof Error ? err.message : String(err),
)
})
}
})
} catch (err) {
// Re-sync failure is non-fatal — log and continue (T-03-13)
console.error(