proxy: end quadratic context storage (R85, the quota outage) #4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/storage-r85"
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?
Outage 2026-10-19: Mongo quota (5131/5120 MB) block-wrote the cluster, all services crash-looped a night. Cause: history+jobs stored the FULL context TWICE per request. Fix: terminal jobs strip payload; history keeps only the new turn + response; 7-day TTL on both. proxy 23+10.
Rosa's review (all three points): 1. Blocker: _central_origin_url no longer reads central's local remote (which may still be the OLD location mid-migration — on this box it literally is GitHub). The canonical URL comes from TG_SOURCE_REPO_URL only; empty = no origin management at all. 2. Design: divergence is REPORTED ('origin: X -> Y (TG_SOURCE_REPO_URL)') and the flip is explicitly policy-gated, never silent inference. 3. Leak: URL is credential-stripped (urlsplit hostname/path only) before embedding, and quoted (SRC="...") everywhere in the generated script. cat-file sha gate + actionable failure message unchanged (she approved those as-is). Verified by generating the script: no creds in output, quoted SRC, gate present; unset policy -> no origin block. runtime suite: 145 passed, 3 skippedAPPROVED. I traced the actual storage path rather than reading the PR title, because the title said "quadratic context storage" and the first thing in the diff was a TTL index, which is a backstop rather than the fix. The real fix is at dispatcher.py and it is correct.
The core change. R34 wrote the whole
job["messages"]intodb.historyon every request. Sincemessagesis the growing conversation, storing it per request is quadratic in turn count — which is how a quota got consumed. The new code stores only the newest user message asnew_turnplus the response. That is the right shape: the canonical transcript lives inagent_transcripts, and history becomes a request log rather than a second copy of the conversation.Verified no consumer breaks. I grepped the whole repo for readers of
history.messages:GET /history(jobs.py:132) readsdb.jobswith{"messages": 0, "tools": 0}projected out — it never touched the history collection.historycollection at all.Also checked the two things a TTL index can get wrong:
jobsTTL is onfinished_atwithpartialFilterExpression: status in [done, failed]. Queued and running jobs havefinished_at: None— null is not a BSON date, so they are never TTL-eligible. No live job can be reaped.historyTTL onts, which is set bynow()on every insert. Fine.And I like the
$unsetI did not expect: the done/fail write stripsmessagesandtoolsoff the job document itself, so the payload is not left sitting injobseither. Her test asserts exactly that ("$unset" in done[0]), plustotal_h < 5000as a size ceiling for history. That is a real regression guard, not a smoke test.Two notes, neither blocking:
ARCHITECTURE.md:155now contradicts the code. It still says "full content stored: prompts, completions, tool calls, per job — feeds the web history viewer". The code no longer stores that, and the viewer it mentions does not exist. That doc is what a future agent will read to understand the design, so it should be corrected in the same breath rather than drift.GET /jobs/{job_id}(jobs.py:145) returns the whole job document includingresult. If a result carries the completion text, that is a second large payload — worth checking whether it should also be projected down, though it is a read path, not a write path, so it does not cause growth.Merge status, and this is the blocker: I have now submitted an APPROVED review on this repo three times (#2, #3, #4) and every one returns state PENDING, and merge returns 405 "Does not have enough approvals". So on TreeGent my approval is recorded but not counted — unlike cm8b-ops and cm8b-tt where my merges land. That is a branch-protection approval requirement I am not on the list for. @felix: either add me as an allowed approver on TreeGent, or every TreeGent PR needs you or Heike. I cannot merge here, and I have stopped retrying.