Skip to content

perf(imap): write only the memberships a full enumeration changes - #750

Closed
exactmike wants to merge 1 commit into
kenn-io:mainfrom
local-ha:perf/imap-reset-membership-diff
Closed

perf(imap): write only the memberships a full enumeration changes#750
exactmike wants to merge 1 commit into
kenn-io:mainfrom
local-ha:perf/imap-reset-membership-diff

Conversation

@exactmike

Copy link
Copy Markdown
Contributor

Closes #749

A full enumeration used to rewrite every saved membership row of a mailbox
and rebuild every message's labels, even when almost nothing had changed.
The store now diffs against the saved rows and writes only the memberships
whose message or flags moved, rebuilding labels only for those messages.

A reset that empties a mailbox, such as a new UIDVALIDITY epoch, still
clears it in one statement. Tombstones are unaffected. A message whose
membership never changes again after an earlier partial label merge no
longer gets its labels rebuilt by a later full enumeration. #748 proposes an
explicit repair command for that case.

On a 118,000-message Microsoft 365 account, a forced full enumeration's
store transaction dropped from 282s to 2.9s. Final memberships, folder
states, labels and tombstones matched.

No configuration or usage changes.

A Reset delta republishes an entire mailbox, and applyIMAPMailboxDeltas
deleted and reinserted every saved membership row, then rebuilt labels
and tombstone state for every message it touched. On a 96,000-message
INBOX that is roughly 700,000 statements in one write transaction --
`sql tx slow duration_ms=230461` -- for a set of rows that is almost
entirely unchanged.

Read the mailbox's saved rows once, remove the UIDs the reset does not
republish, and write only the memberships whose message or flags moved.
Only those messages enter the label reconciliation pass. Flags are
compared after decoding, so SQLite text and PostgreSQL JSONB compare
alike, and a row whose saved flags do not decode is always rewritten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhzbNgimfaBhPUSMzB8v2A
@roborev-ci

roborev-ci Bot commented Sep 3, 2026

Copy link
Copy Markdown

roborev: Combined Review (fcf264b)

No issues found.


Reviewers: 2 done | Synthesis: codex | Total: 3m55s

@wesm wesm self-assigned this Sep 4, 2026
@wesm

wesm commented Sep 4, 2026

Copy link
Copy Markdown
Member

rebasing

@wesm

wesm commented Sep 4, 2026

Copy link
Copy Markdown
Member

superseded by #765

@wesm wesm closed this Sep 4, 2026
wesm added a commit that referenced this pull request Sep 5, 2026
Supersedes #750. Closes #749.

A full IMAP enumeration previously rewrote every saved membership row in a
mailbox and rebuilt every message's labels, even when almost nothing changed.
The store now diffs the enumeration against saved rows, writes only memberships
whose message or flags changed, and rebuilds labels only for affected messages.

A reset that empties a mailbox, such as a new UIDVALIDITY epoch, still clears
it in one statement. Tombstone behavior is unchanged. A membership that never
changes after an earlier partial label merge is no longer repaired as a side
effect of a later full enumeration; #748 tracks an explicit repair path for
that case.

On a 118,000-message Microsoft 365 account, a forced full enumeration's store
transaction dropped from 282 seconds to 2.9 seconds while preserving final
memberships, folder states, labels, and tombstones.

No configuration or usage changes.


Co-authored-by: Wes McKinney <wesm@users.noreply.github.com>
@exactmike
exactmike deleted the perf/imap-reset-membership-diff branch September 5, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

A full IMAP enumeration rewrites every membership row it already holds

2 participants