A4 of the service-class pair (SELF-ENGINE-LIFECYCLE-SPRINT, David-directed:
'why do we need manual flushes at all?'). The production disease: 829
caller-scheduled per-write flushes convoying into 45-66s write walls —
cadence hand-rolled a layer above the only layer that can see dirty-node
counts and IO pressure.
- BrainyConfig.persistence: policy 'auto' (DEFAULT) | 'manual', with
flushEveryWrites (512) / flushIntervalMs (30s) / flushOnIdleMs (2s)
triggers. Auto = the engine kicks ONE single-flight BACKGROUND flush at
a threshold or when the store goes quiet; write acks NEVER await it (a
hung flush cannot block a write — pinned); a failed background flush is
LOUD and re-arms the trigger. 'manual' restores caller-owned cadence.
- Triggers wired at both write chokepoints (single-op post-commit +
transact post-commit); idle timer unref'd; close() tears the timer down
and drains the flight before its own final flush.
- RECOVERY SEMANTICS documented on the config: canonical records are
durable per-write regardless of policy — a crash between background
flushes loses derived state only, which converges at next open (epoch
machinery + the new incremental aggregation catch-up), bounded by the
un-flushed window. Never data loss.
Pins: write-count trigger fires one background flush with zero caller
calls · idle trigger · manual never self-flushes · THE ACK LAW (writes
acknowledge under a never-resolving flush). Gates: unit 1917/1917 ·
integration 760 · conformance 27/27 — green WITH auto as the default.