perf(trajectory): connect once per batch, not once per record #143
No reviewers
Labels
No labels
burndown-2026-08
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/advocate
role/director
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/science
role/sysadmin
state
ambient
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/agent-proxy!143
Loading…
Reference in a new issue
No description provided.
Delete branch "task/view-rebuild-connection-churn"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #142, which carries the remaining structural half.
The problem
save_allon both derived trajectory stores wastuple(self.save(r) for r in records), and everysaveopened its own SQLite connection._operational_builder()rebuilds the whole retained ledger through those calls on every request to/v1/trajectory/views/{view_name}and/v1/trajectory/dossiers/{trajectory_id}, so connection setup sat on the critical path of a read endpoint and scaled with ledger size.Measurements
Synthetic ledger of request-lifecycle event pairs, timed in the steady state where nothing has changed and every write is a no-op.
MaterializationStore.save_all, 2000 turns_operational_builder(), 2000 turnsI had assumed
BEGIN IMMEDIATEwas the expensive part and was wrong. A microbenchmark isolating the two candidates over 2000 records:BEGIN IMMEDIATEeach - 158.6 msConnect is the entire cost. The write lock is roughly 7 ms across the whole batch. So the fix is connection reuse, and leaving the per-record transaction exactly as it was.
What is preserved
Per-record semantics are untouched: each record still gets its own
BEGIN IMMEDIATE, the same digest dedupe, and the same insert.with connectioncommits without closing, which leaves the nextBEGIN IMMEDIATEa clean start.savekeeps its signature and now closes the connection it opens, which the previouswith self._connect()never did (the sqlite3 connection context manager commits, it does not close).Verification
tests/test_trajectory_store_batching.py, 3 tests. Mutation-checked: restoring the per-record connect fails the suite. The dedupe test drives five consecutive no-op saves over one shared connection, which is the case the transaction reuse could plausibly break.just format-check,just lint,just typecheck, andpre-commit run --all-filesclean.What this does not fix
The growth curve. Read cost stays linear in ledger size at roughly 0.2 ms per retained turn, because the rebuild still reads and re-materializes everything. Fixing that means choosing between a staleness window, incremental materialization, or cached views, which is a design decision rather than a mechanical one. Filed with numbers and options as #142.
🤖 Generated with Claude Code