fix(db): index decision_ledger_anchors on (row_hash, status) - #9830
Conversation
`anchorBackendsMissingForRowHash` (JSONbored#9489) runs `SELECT DISTINCT backend FROM decision_ledger_anchors WHERE row_hash = ? AND status = 'ok' AND backend IN (...)` once per row being re-anchored, but the table had no index on row_hash — so each call was a full table scan that grows with the anchor ledger. Add migration 0203 creating `decision_ledger_anchors_row_hash_status (row_hash, status)` — row_hash first (the equality predicate), status included so the `status = 'ok'` filter is served from the index rather than a row fetch. Mirrors the decision_ledger_record_id index added in 0198. The migration contains nothing else. (Issue named 0202; that number is now taken, so this is the next contiguous 0203.) A new test asserts the index exists after replaying migrations and that the real query SEARCHes via it (not SCAN); the existing anchorBackendsMissingForRowHash behaviour cases confirm results are unchanged. Closes JSONbored#9652
|
Warning ⏸️ LoopOver review result - manual review recommendedReview updated: 2026-07-29 12:45:12 UTC
Review summary Nits — 3 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9830 +/- ##
=======================================
Coverage 91.59% 91.59%
=======================================
Files 915 915
Lines 112700 112700
Branches 27077 27077
=======================================
Hits 103229 103229
Misses 8144 8144
Partials 1327 1327
Flags with carried forward coverage won't be shown. Click here to find out more. |
What & why
anchorBackendsMissingForRowHash(#9489,src/review/ledger-anchor-persistence.ts) runsonce per row being re-anchored, but
decision_ledger_anchorshad no index onrow_hash. So each call was a full table scan whose cost grows with the anchor ledger.The fix
Add migration 0203 creating:
row_hashleads (the equality predicate);statusis included so thestatus = 'ok'filter is served from the index rather than a row fetch. This mirrors thedecision_ledger_record_idindex added inmigrations/0198. The migration contains nothing else — no schema or data change.Tests (
test/unit/ledger-anchor-persistence.test.ts)migrations/**(viacreateTestEnv), the indexdecision_ledger_anchors_row_hash_statusexists, andEXPLAIN QUERY PLANfor the exactanchorBackendsMissingForRowHashpredicate SEARCHes via it, not SCANs (fails without the migration).anchorBackendsMissingForRowHashbehaviour cases (all-missing / some-present / all-present / different-rowHash) confirm results are unchanged after the migration.Validation
npm run db:migrations:checkgreen (contiguous 0001..0203);npm run db:schema-drift:checkgreen (index on a raw-SQL table, no Drizzle change);npm run typecheckgreen.migrations/**is outside Codecov's include, so the migration carries no coverage obligation; the test importscreateTestEnv, so shards see realsrc/**.git diff --check <base> HEADclean; diff is the one migration + its test, nosrc/**source change.Closes #9652