Repository navigation
perf(store): move runtime SQL outside packet-store locks - #495
Conversation
Review — CS-Coordinator PR#495 — head 8ba8a3aVerdict: APPROVE with one condition before merge: a staging soak (see below). Reviewed by code reading plus tests on the merged tree: current master What I checked
Condition before mergeThis is a +1,070-line refactor of hot lock paths, after the race history in #470/#475. Before merging, I recommend a few hours on staging under live ingest, as we did for #494, deploying master + this PR. Check:
Nits
|
|
Staging soak passed (master
Latency was equal or better than before the deploy:
Packet detail took 0.24 s. Node paths took 0.56 s warm (2.0 s cold), against 0.92 s on production v0.2.5. The review condition is met; merging. |
Summary
Relates to #412.
Move runtime packet/detail/filter/analytics database work outside
PacketStore.muwhile retaining synchronous cold/expired-cache behavior. A slow SQL request may still delay its caller, but must not create a packet-store reader convoy that holds unrelated ingest writers back.No schema, configuration, frontend, ingestor-binary or workflow changes. Auto-merge remains disabled.
Tests and independent review
-race: pass (15.034 s); vet, gofmt and diff checks clean.10adb2bf24a9941e50aca122203799f3caef6b34. Its focused-raceexecution passes (2.909 s), including all nineteen convoy cases and the invariants above.GitHub/Linux CI is separate evidence and will be reported after the new PR run.
Measured trade-off
Go 1.26.3, macOS arm64 / Apple M5; 30,000 in-memory transmissions. The contention benchmark deliberately holds the SQL pool for 20 ms and uses an actual ingest-style store writer. It is a controlled local scenario, not a deployment latency measurement.
The immutable snapshot adds a small uncontended request cost; this is not hidden as an across-the-board speedup. Per-request work stays bounded by the selected result/observations and existing cache bounds.
Lock and staleness contract
Cold/expired SQL-backed caches still refresh synchronously outside the packet-store lock. There is no new stale/temporarily-unfiltered response mode. A request owns its captured metadata snapshot even if invalidation happens later; invalidated SQL cannot republish that snapshot into the cache. Resolved-path enrichment can reflect a newer database state than the store snapshot, as before, but never rereads mutable transmission fields after unlocking.
The legacy startup
Loadpublication section still holds its exclusive store lock around SQL before HTTP serving. Startup/chunk loader methods are explicit guard exceptions because of their nested publication lifecycle; this PR does not claim every SQL call in the entire program is lock-free. Existing outside-lock chunk reads and bounded merge sections are preserved.EvictStaledid not actually perform the SQL described by its old comment on this baseline; its behavior is preserved and the comment corrected.RunEvictionkeeps its existing outside-lock evidence batch. No broader eviction redesign is included.Attribution
Historical design reference, adapted rather than cherry-picked wholesale: