WIP: merge queue: checking main (389bd97) and #459 together #461

Closed
mergify[bot] wants to merge 2 commits from mergify/merge-queue/b6900d038b into main
2 Commits
Author SHA1 Message Date
Mergify 4cfaa5fc55 Merge of #459 2026-07-08 20:54:37 +00:00
JMR-dev 52da77b6a0 perf(sync): pause background backfill while a message is opening
Opening an uncached message stalled ~35-74s (avg 48s) behind the reader
spinner because the on-demand IMAP body fetch has no priority over the
continuous full-history backfill (#12) and loses the race for the
account's IMAP throughput (connect-per-op client, no shared lock).

Introduce InteractiveImapGate (@Singleton), a process-wide priority
signal mirroring MailMaintenanceGate/AccountThrottleGate (#360):

- MailRepositoryImpl wraps the user-facing IMAP paths (openMessage,
  inlineImages, downloadAttachment, buildReplyDraft) in withInteractive
  {}, which raises an in-flight counter for the duration and always
  lowers it in a finally, so a failed fetch can never strand it.
- MailBackfiller parks (awaitInteractiveIdle) at its per-page yield
  point while the counter is non-zero, resuming the instant it clears.
  This is also the slice's first yield point, so a slice never begins a
  page while a user is waiting on a body.
- Backfill's own content prefetch bypasses the gate (calls
  ensureAttachmentFile directly) so it never yields to itself.

A counter, not a mutex, is used so overlapping interactive fetches run
concurrently and backfill waits for all to clear. PII-free AppLog
park/resume breadcrumbs (accountLogRef) at the backfill yield points.

Builds on #360's throttle framework (orthogonal: that backs off after a
provider rejects background work; this yields to a foreground fetch).

Tests: InteractiveImapGateTest (counter/park/resume/error-release/
concurrency + Turbine), MailBackfillerTest park+resume+no-deadlock,
MailRepositoryImplTest gate-held-during-open, and
InteractiveImapGateInstrumentedTest (on-device pause/resume across the
CI API matrix).

Closes #355
2026-07-08 15:17:56 -05:00