Spike: flag-gated IMAP connection reuse for folder-open
A time-boxed spike for #125, prototyping the per-account connection reuse the investigation (#126) recommended and deferred. This references #125 but does not close it — the feature needs real-device / real-account validation before the default flips on.
The folder-open network path currently re-establishes a full, freshly-authenticated IMAP connection on every operation (CONNECT + TLS + LOGIN … LOGOUT) — no pooling/keep-alive. Only EXAMINE + FETCH is intrinsic to opening a folder; the setup group is the majority of the round-trips and is avoidable on the 2nd+ operation if a connection is reused.
What's here
ImapConnectionCache — keeps one authenticated Store alive per account, guarded by a per-account mutex, keyed by connection identity (host/port/user/security/mechanism — not the rotating secret), with lazy catch-and-retry-once stale handling. closeReusedConnections() is the only eviction today.
ImapClient flag — a reuseConnections boolean, OFF by default via the @Inject no-arg constructor. With it off, withStore is byte-for-byte the previous connect + LOGOUT-per-call and the cache is never allocated, so it cannot destabilize main. Only the harness opts in.
Harness proof — ImapFolderOpenLatencyTest flips the flag on and asserts the collapse against real in-process IMAP (CountingImapProxy + GreenMail). Localhost is ~0 RTT, so this proves the connection is reused (structure), not wall-clock latency — no numbers are fabricated.
docs/perf/issue-125-connection-reuse-spike.md — prototype design, the flag-off-vs-on proof, per-decision trade-offs, feasibility verdict, and the refined real-device validation plan.
Deterministic proof (flag off vs on), for N = 3 folder-opens
Scenario
TCP conns
LOGIN
EXAMINE
LOGOUT
Flag OFF — N folder-opens
N (3)
N (3)
N (3)
N (3)
Flag ON — N folder-opens
1
1
N (3)
1
Flag OFF — open folder + read msg
2
2
1E+1S
2
Flag ON — open folder + read msg
1
1
1E+1S
1
Setup drops from once per operation to once per account; the intrinsic per-folder EXAMINE is unchanged. All 6 cases pass on the JVM fast gate.
Deliberately left open (needs measurement, not a guess)
Single connection vs. bounded pool (head-of-line blocking), idle-eviction timeout, stale-probe strategy (NOOP vs retry), IDLE per-account connection budget (#90 — reuse is an additional socket to IDLE), low-battery eviction (#88/#89/#90), and mutation-retry idempotency. See the doc for the per-decision stance + the 6-step real-device validation plan.
Scope
IMAP client / connection lifecycle + the GreenMail harness + the design doc only. No DB/keystore (#118) or mailbox UI (#130) changes. IDLE is untouched (keeps its own dedicated connection).
## Spike: flag-gated IMAP connection reuse for folder-open
A time-boxed **spike** for #125, prototyping the per-account connection reuse the investigation (#126) recommended and deferred. This **references #125 but does not close it** — the feature needs real-device / real-account validation before the default flips on.
The folder-open network path currently re-establishes a full, freshly-authenticated IMAP connection on every operation (`CONNECT + TLS + LOGIN … LOGOUT`) — no pooling/keep-alive. Only `EXAMINE + FETCH` is intrinsic to opening a folder; the setup group is the majority of the round-trips and is avoidable on the 2nd+ operation if a connection is reused.
### What's here
- **`ImapConnectionCache`** — keeps one authenticated `Store` alive per account, guarded by a per-account mutex, keyed by connection identity (host/port/user/security/mechanism — **not** the rotating secret), with lazy catch-and-retry-once stale handling. `closeReusedConnections()` is the only eviction today.
- **`ImapClient` flag** — a `reuseConnections` boolean, **OFF by default** via the `@Inject` no-arg constructor. With it off, `withStore` is byte-for-byte the previous connect + `LOGOUT`-per-call and the cache is never allocated, so it cannot destabilize `main`. Only the harness opts in.
- **Harness proof** — `ImapFolderOpenLatencyTest` flips the flag on and asserts the collapse against real in-process IMAP (`CountingImapProxy` + GreenMail). Localhost is ~0 RTT, so this proves the connection is **reused** (structure), not wall-clock latency — no numbers are fabricated.
- **`docs/perf/issue-125-connection-reuse-spike.md`** — prototype design, the flag-off-vs-on proof, per-decision trade-offs, feasibility verdict, and the refined real-device validation plan.
### Deterministic proof (flag off vs on), for N = 3 folder-opens
| Scenario | TCP conns | LOGIN | EXAMINE | LOGOUT |
|----------|-----------|-------|---------|--------|
| Flag OFF — N folder-opens | N (3) | N (3) | N (3) | N (3) |
| **Flag ON — N folder-opens** | **1** | **1** | N (3) | **1** |
| Flag OFF — open folder + read msg | 2 | 2 | 1E+1S | 2 |
| **Flag ON — open folder + read msg** | **1** | **1** | 1E+1S | **1** |
Setup drops from *once per operation* to *once per account*; the intrinsic per-folder `EXAMINE` is unchanged. All 6 cases pass on the JVM fast gate.
### Deliberately left open (needs measurement, not a guess)
Single connection vs. bounded pool (head-of-line blocking), idle-eviction timeout, stale-probe strategy (NOOP vs retry), IDLE per-account connection budget (#90 — reuse is an *additional* socket to IDLE), low-battery eviction (#88/#89/#90), and mutation-retry idempotency. See the doc for the per-decision stance + the 6-step real-device validation plan.
### Scope
IMAP client / connection lifecycle + the GreenMail harness + the design doc only. No DB/keystore (#118) or mailbox UI (#130) changes. IDLE is untouched (keeps its own dedicated connection).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Spike: flag-gated IMAP connection reuse for folder-open
A time-boxed spike for #125, prototyping the per-account connection reuse the investigation (#126) recommended and deferred. This references #125 but does not close it — the feature needs real-device / real-account validation before the default flips on.
The folder-open network path currently re-establishes a full, freshly-authenticated IMAP connection on every operation (
CONNECT + TLS + LOGIN … LOGOUT) — no pooling/keep-alive. OnlyEXAMINE + FETCHis intrinsic to opening a folder; the setup group is the majority of the round-trips and is avoidable on the 2nd+ operation if a connection is reused.What's here
ImapConnectionCache— keeps one authenticatedStorealive per account, guarded by a per-account mutex, keyed by connection identity (host/port/user/security/mechanism — not the rotating secret), with lazy catch-and-retry-once stale handling.closeReusedConnections()is the only eviction today.ImapClientflag — areuseConnectionsboolean, OFF by default via the@Injectno-arg constructor. With it off,withStoreis byte-for-byte the previous connect +LOGOUT-per-call and the cache is never allocated, so it cannot destabilizemain. Only the harness opts in.ImapFolderOpenLatencyTestflips the flag on and asserts the collapse against real in-process IMAP (CountingImapProxy+ GreenMail). Localhost is ~0 RTT, so this proves the connection is reused (structure), not wall-clock latency — no numbers are fabricated.docs/perf/issue-125-connection-reuse-spike.md— prototype design, the flag-off-vs-on proof, per-decision trade-offs, feasibility verdict, and the refined real-device validation plan.Deterministic proof (flag off vs on), for N = 3 folder-opens
Setup drops from once per operation to once per account; the intrinsic per-folder
EXAMINEis unchanged. All 6 cases pass on the JVM fast gate.Deliberately left open (needs measurement, not a guess)
Single connection vs. bounded pool (head-of-line blocking), idle-eviction timeout, stale-probe strategy (NOOP vs retry), IDLE per-account connection budget (#90 — reuse is an additional socket to IDLE), low-battery eviction (#88/#89/#90), and mutation-retry idempotency. See the doc for the per-decision stance + the 6-step real-device validation plan.
Scope
IMAP client / connection lifecycle + the GreenMail harness + the design doc only. No DB/keystore (#118) or mailbox UI (#130) changes. IDLE is untouched (keeps its own dedicated connection).
🤖 Generated with Claude Code