Repository navigation
perf(history): move integrity scans off the serving thread - #7972
Conversation
Validate persisted indexes once per handle and every five minutes in a read-only worker while preserving automatic corruption repair. Bound read retries, keep operational failures nondestructive, and drain old scanners before replacing files. Cover warm reads, real B-tree corruption, analytics, routing evidence, ingestion and worker lifetime races with native Bun tests. Refs lidge-jun#7966
|
✅ Deterministic PR hygiene checks passed. |
Walkthrough
Merge Risk:
|
|
Coordination snapshot for 87db01f, checked on 2026-10-30. This PR stays independent. Latest upstream Current CI and reviewCross-platform CI 40991885848 and Catalog async contracts 40991885850 succeeded. The CI test checkout was The relevant cases actually ran on Ubuntu / Bun 1.4.4:
The Windows matrix job 123856074107 is skipped with zero steps. The successful runner-selector job ran on Ubuntu. Neither is native Windows validation. All-event Actions searches of the head and inspection of PR discussion found no separate native Windows result. At inspection, there were no submitted PR reviews or review threads. The CodeRabbit report found no actionable merge-blocking issue; its docstring-coverage warning remains. Requested human review has not been substituted with CI success. Native Windows verification remains pendingThe existing Windows verification owner needs to run the three files above at this exact head with native Bun 1.4.4, preserving the test preload, isolated home, queue guards, and existing storage limits. This is a coordination request, not an acknowledgement or completed execution. In addition, actual cancellation/file replacement needs native evidence:
The deterministic No existing workflow input selects only these Windows tests. The current CI workflow offers Independent #7971 combinationPinned #7971 head: Native Linux results: five new integration cases passed (153 assertions), plus 43 unchanged slug-codec cases (119 assertions). Cold model-cache decoding, initial history validation, provider/model/accountRef separation, missing-index reconstruction, and empty-history exclusion behaved as expected. Pending health obeyed After a real worker verdict, cached unknown health remained until the existing 1,500 ms TTL expired. Recovery was verified after the real wait, without clearing the cache. A separate exact-target diagnostic failed two cases both on #7971 alone and on the combination: policy/combo candidate Shared registration auditPinned #7376
#7972 overlaps #7376/#7931 only in the registry and golden, not runtime source or test bodies. Their shared source paths remain with their existing owners. Fork #796/#798 remain separate with their existing task owners; no fixes were taken over. No merge, force push, installed-app replacement, security/permission change, workflow dispatch, or production-source edit was performed for this coordination pass. |
|
Windows follow-up for
The disposable harness uses synchronous pass-through SQLite/worker logging and Bun module instrumentation around the existing guarded filesystem functions. It observes actual production calls rather than substituting verdicts, file operations or Earlier wrapper-startup, instrumentation and test-selection failures are retained separately and are not counted as product failures or passes. Periodic scheduling used an injected clock; this does not claim a real-time five-minute soak, native macOS, installed-app/live-database validation, or merge acceptance. No production configuration, account data or live database was changed. |
|
Maintainer integration into
Closes #7966; the issue will be closed manually after merge, because PRs into |
Summary
Closes #7966.
Healthy history refreshes currently scan the complete SQLite index synchronously, even when a selective query needs one row. Move full integrity checks into the existing history worker while keeping schema/source/offset validation and automatic reconstruction from canonical
usage.jsonl.CORRUPT/NOTADBerrors. History pages, row lookup and analytics retry a synchronous read once after repair; routing health marks the live generation for repair, and incremental-ingest corruption also rebuilds.BUSY,LOCKED, I/O, disk-full and worker-start failures separate from corruption. Check failures back off for 30 seconds without deleting a healthy index.Based on current upstream
dev@3ea89653f5727aea41948ddbd5e833f74afe3e36. The reported indexer is identical inmain@d844ff4af67c98271be1c1451e7583d36c323527. The partial-tail optimization in #7680 is preserved.Strategy and tradeoff
An initialization-only check removes repeated work but leaves untouched damaged pages undetected in a long-running process. A timer executing synchronous SQLite on the serving thread still stalls that thread. This change instead uses first-use and demand-triggered periodic worker validation, plus immediate repair when a statement encounters corruption. Initial validation still takes time proportional to index size and may cost worker startup latency; periodic detection is not instantaneous. Existing source identity, truncation, worker-rebuild cooldown/fallback, pagination and canonical-ledger rules stay in force.
Verification
Native Linux x64 Bun 1.4.4 (
38afee6c8), real Bun SQLite and real workers, frozen dependencies. The published tree is the exact locally validated tree8ba2b1ac13b78cfbe33639bc85f57e95e3c66474.139 passed / 0 failed / 2,708 assertions across these files, each executed in a separate native
bun testprocess:The 20 new cases prove zero serving-thread full-check SQL during repeated page/id/status/routing reads; initial and periodic single-flight behavior; cooldowns; actual corrupted B-tree detection/rebuilding; error-driven history, analytics, health and tail-ingest repair; bounded retries; and close/manual-rebuild/source-replacement races. The damaged secondary-index fixture leaves schema metadata and ordinary timestamp queries readable, so it cannot pass merely through corrupt-header handling. Recovery verifies canonical ledger bytes are unchanged.
Also passed:
bun run typecheck— 2,245 files, zero type errors.bun run structure:check.bun run privacy:scan.git diff --cached --check.cd docs-site && bun run buildwith telemetry disabled and a writable scratchXDG_CONFIG_HOME— 625 pages, 90,515 internal links checked.Synthetic performance check
Same synthetic 100,000-row ledger with three attempts per record and unique API-key selectors; 122,866,680 canonical bytes and a 234,721,280-byte index. Eight sequential selective
limit=1indexer queries, after reopening/validating, compared against the exact base commit:The first patched lookup awaits one worker check; its serving thread remains responsive. Neither implementation changes the canonical bytes. These are synthetic indexer-level measurements, not a reproduction of the reporter's 4.8 GB production database or HTTP latency.
Validation scope
The repository wrapper stalled in
bun test --isolate --parallel=2startup before any test cases on the unmodified base. The finalbun run test:changed --parallel=2likewise did not start cases and was terminated after a 45-second bound (exit 124). Under the documented focused-validation resource exception, the relevant suites above were executed directly and passed; the full local suite is not claimed. Native Windows 11 x64/Bun 1.4.4 follow-up now passed the three unchanged history suites (62 tests / 1,854 assertions), a real-worker component fixture (27 assertions), and three production-indexer integration cases in two focused runs (60 + 40 assertions). Those cases cover manual rebuild, close/reopen before drain completion, and ordinary-query source-identity replacement while a periodic scan is actually blocked in SQLite. The production filesystem calls occur after the old worker's actual exit barrier; expected replacement rows and metadata were checked. See the native validation report for instrumentation and execution limits. Native macOS, a real-time five-minute soak, installed-app/live-database behavior and maintainer acceptance remain separate.Checklist
Summary by CodeRabbit