fix(06): WR-06 bound post-write targeted resync with 10s timeout so a hang cannot wedge drain
This commit is contained in:
@@ -155,6 +155,14 @@ export function assembleRruleString(
|
||||
*/
|
||||
let isDraining = false
|
||||
|
||||
/**
|
||||
* WR-06: max time to wait on the post-write targeted re-sync before marking the
|
||||
* outbox row 'done'. A stalled Fastmail connection cannot wedge the single-process
|
||||
* drain loop beyond this cap; the PWA's next sync-status poll reconciles any cache
|
||||
* that the timed-out re-sync did not refresh.
|
||||
*/
|
||||
const RESYNC_TIMEOUT_MS = 10_000
|
||||
|
||||
// ── Credential + client loading ──────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
@@ -690,7 +698,20 @@ export async function runOutboxDrain(): Promise<void> {
|
||||
// raced the re-sync and returned stale cache (deleted event still
|
||||
// present, edit not yet applied) — forcing a manual refresh. Re-syncing
|
||||
// first means 'done' guarantees the cache already reflects the write.
|
||||
await triggerTargetedResync(row.calendarUrl, row.userId, clientCache)
|
||||
//
|
||||
// WR-06: bound the re-sync with a timeout. triggerTargetedResync does
|
||||
// unbounded network I/O against Fastmail (fetchCalendars + syncCalendar);
|
||||
// a hang would leave this row 'pending' from the DB's view for the full
|
||||
// duration, the 15s isDraining guard would no-op the next cycle, and the
|
||||
// PWA would poll 'pending' indefinitely — wedging the single-process
|
||||
// drain loop. On timeout we proceed to mark 'done' and let the PWA's next
|
||||
// poll/refetch reconcile (the same documented refetch path the eager
|
||||
// re-sync was optimizing). triggerTargetedResync already swallows its own
|
||||
// errors, so the race only needs to cap the wait.
|
||||
await Promise.race([
|
||||
triggerTargetedResync(row.calendarUrl, row.userId, clientCache),
|
||||
new Promise<void>((resolve) => setTimeout(resolve, RESYNC_TIMEOUT_MS)),
|
||||
])
|
||||
await db
|
||||
.update(calendarOutbox)
|
||||
.set({ status: 'done' })
|
||||
|
||||
Reference in New Issue
Block a user