fix: Batch vector upserts + background timeout budget (Fixes BATTLE-MAGE-5) - #144
Conversation
…AGE-5) The 2s VECTOR_OP_TIMEOUT_MS was sized for interactive paths (KB recall, search arms inside a turn) but also governed the background embed pipelines, where one upsert carries a whole file's chunks (up to ~130) for server-side embedding — legitimately seconds of work. Large files timed out on every 5-minute tick, permanently stalling the code index on exactly the files most worth indexing, while the un-abortable request often succeeded server-side anyway (wasted embedding spend on each retry). The docs pipeline had the same bug latent: it upserts an entire corpus in one call, fire-and-forget. - vectorUpsert now batches at UPSERT_BATCH_SIZE (20) with a per-batch timeout, stopping on the first failed batch; deterministic ids make the caller's retry of already-written batches idempotent - Per-call timeout override: background pipelines (code index, docs embed) pass VECTOR_BACKGROUND_TIMEOUT_MS (30s), absorbed by the ticks' existing wall-clock budgets; interactive paths keep 2s Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds batched, deadline-aware upserting to ChangesVector Upsert Timeout and Batching
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant vectorUpsert
participant withTimeout
participant Store
Caller->>vectorUpsert: vectorUpsert(namespace, items, opts.timeoutMs)
vectorUpsert->>vectorUpsert: compute end-to-end deadline
loop each batch of UPSERT_BATCH_SIZE
vectorUpsert->>vectorUpsert: check remaining time
vectorUpsert->>withTimeout: race(store.upsert(batch), remainingMs)
withTimeout->>Store: upsert(batch)
Store-->>withTimeout: result or timeout
withTimeout-->>vectorUpsert: success or VectorTimeoutError
end
vectorUpsert-->>Caller: true/false
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoFix background vector upserts with batching + per-call timeout override
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
…onstant flow in tests - timeoutMs is now a per-CALL deadline: each batch races the remaining budget, so a multi-batch upsert can never exceed the caller's cap (previously each batch got a fresh budget — batches × 30s could overrun the tick's wall-clock). Deadline test pins 3×12s batches failing at a 30s cap. - Test assertions reference VECTOR_BACKGROUND_TIMEOUT_MS instead of a raw 30_000 literal; the vector mocks now spread importOriginal so real constants flow through and can't drift from production. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Second production finding from the code index's first real run (Sentry BATTLE-MAGE-5, 3 occurrences — one per cron tick). Different class from BATTLE-MAGE-4: not a misconfiguration but a timeout budget sized for the wrong workload.
VECTOR_OP_TIMEOUT_MS(2s) is right for interactive paths — recall must never stall a turn — but it also governed the background embed pipelines, where a single upsert carries an entire file's chunks (up to ~130) for server-side embedding. Big files therefore timed out on every 5-minute tick: the index permanently stalled on exactly the files most worth indexing, and since the SDK exposes no cancellation (established in #134's review), each timed-out request likely completed server-side anyway — burning embedding spend per retry while never recording success. The docs pipeline carried the same bug latently (whole corpus in one fire-and-forget call).Fix
vectorUpsert: at mostUPSERT_BATCH_SIZE(20) items per underlying store call, sequential, stop on first failure. Deterministic chunk ids make retries of already-written batches idempotent, so mid-list failure semantics stay safe for both the manifest (code index) and the pointer swap (docs).VECTOR_BACKGROUND_TIMEOUT_MS(30s — absorbed by the ticks' existing 180s wall-clock budgets); interactive paths and KB saves keep the 2s default.VectorTimeoutErrornow reports the actual budget it enforced.Testing
TDD: 6 new tests confirmed RED first — batch splitting (20/20/5), stop-on-first-failed-batch, at-size single call, override survives past the default budget and fails past its own, default still enforced when unset, constants pinned. Call-site assertions updated to include the background option. Full suite 951 passing, typecheck clean. No cassette impact (vector env is force-unset in behavior evals).
Fixes BATTLE-MAGE-5 (Sentry)
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes