chore(search): make indexed org search dormant behind a single gate and add DB recovery tooling - #8243
chore(search): make indexed org search dormant behind a single gate and add DB recovery tooling#8243waleedlatif1 wants to merge 6 commits into
Conversation
Live Search is the only active Sim Search backend. The indexed backend (retrieval over is_search_index knowledge bases) stays in the tree for a possible re-enable, so it now lives in one dormant module behind one switch. - Move the exclusively-indexed code into apps/sim/lib/sim-search/indexed/ with git mv: scoped owner search, indexed document reads, Tin keyword ranking, and the projection-fill probe. Shared code (projections, projector, member/ACL connector machinery, source overview/setup, prewarm) stays where it is. README documents the dormant state, the gate, re-enable steps, and the DB objects it depends on. - Add isIndexedOrgSearchEnabled() in indexed/gate.ts (the inverse of SIM_SEARCH_LIVE) and use it at every indexed branch: the internal search route, MCP tools, Sim's search/read tools, the indexed document page, shared retrieval, and connector indexing policy. - Add check:indexed-org-search-boundary (runs in check:audits): outside the directory only allowlisted entry files may import the use-case or retrieval barrel, each must import the gate, and no deep imports. - Refuse a search that names a search-index knowledge base while dormant (Knowledge block, internal, v1, v2) with SearchIndexDormantError -> 409 "This search index is inactive; use Sim Search." Workspace knowledge bases are unaffected. - While dormant, the projector writes no embedding_keyword_tin rows and the source/ACL fill passes over search-index rows; the decision is passed into packages/db from the app caller. Workspace projection is unchanged. - Cap the projection-fill probe at 250 ms of the leg budget and remember an unknown answer as unfilled for 5 s instead of re-probing every search.
Organization indexed search is dormant now that live search serves those queries, but an organization search index can still hold most of the knowledge search rows and all of the Tin keyword projection, inflating the shared vector index for every workspace search. This adds an ordered, resumable runbook and operator scripts to reclaim that space. Every script only reads unless --execute is passed. - disable-tin-projection: drops the three Tin sync triggers and truncates embedding_keyword_tin in one transaction, with short lock timeouts retried within a budget. The shared document ACL fan-out is left intact and becomes a probe of an empty table. - restore-tin-projection: reinstalls those triggers from the 0019 and 0024 migration functions themselves, with an optional 0019 backfill. - delete-search-index-documents: deletes one search index's connector documents and chunks in cursor pages, mirroring the app's connector cleanup worker. It refuses unless the base is a search index and every live connector is paused or disabled with no sync lease, re-checked before every page. Storage objects are queued through the app's own storage cleanup outbox in the deleting transaction, with a backlog ceiling. The knowledge base and connectors are kept; their listing cursors are reset so a resumed connector lists everything again. Deletes fire no row triggers and write no projector marks, since projection rows go by foreign-key cascade. - maintenance: health report, REINDEX INDEX CONCURRENTLY (HNSW first, before vacuum) and one-table-at-a-time VACUUM (VERBOSE, ANALYZE). Unit tests cover the guards, paging and resume, retries, backpressure and dry runs. A local-only PostgreSQL integration test exercises the real scripts end to end and is not registered in CI. No migration or schema changes.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
There was a problem hiding this comment.
All reported issues were addressed across 70 files
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
…n and reset member relist state Each deleting transaction share-locks the search index and its connectors and re-decides the guard, so a connector resumed between pages waits for the page in flight and the next page refuses. Every document-deleting transaction also resets the stopped connectors' listing state, now including the directory checkpoint and each member's retry time, so a run stopped partway never leaves a connector that would skip deleted documents on resume.
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
The v1 route refuses a dormant search index before billing admission, so the caller sees why the request cannot run rather than its usage. Each search waits on a shared projection probe no longer than its own share or deadline. The boundary audit requires allowlisted entries to call the gate, not only import it. The deletion script accepts only organization-owned search indexes and deletes chunks only of documents the connectors still own, so a document detached mid-run keeps its chunks.
…nk name collision Turbopack truncates chunk content hashes to seven characters (vercel/next.js#97765), and this branch's module graph produced two different server chunks with the same name, failing the build. Renaming the module re-rolls the hash, as #7593 did; the collision can recur on unrelated changes until Next ships untruncated hashes.
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 70 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
…dary audit and use sleep for the probe wait
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
| const unanswered = sleep(waitMs).then(() => undefined) | ||
| return (await Promise.race([answer.catch(() => undefined), unanswered])) ?? false |
There was a problem hiding this comment.
Summary
lib/sim-search/indexed/(history kept) with a README covering what it is, the gate, re-enable steps, and the DB objects it depends onisIndexedOrgSearchEnabled()(indexed/gate.ts, inverse ofSIM_SEARCH_LIVE); newcheck:indexed-org-search-boundaryaudit fails on any import into the dormant module outside a small allowlist of gated entry pointsapps/sim/scripts/dormant-org-search/runbook + scripts (dry-run by default) to recover DB health: drop Tin triggers and truncate the Tin projection (with restore), guarded resumable batched deletion of a search-index knowledge base's connector documents (storage cleanup via the app's outbox), then reindex/vacuumType of Change
Testing
New unit tests for the gate, 409 paths, projector skips, probe cap, audit script, and ops script guards (each fails on the old code); knowledge/sim-search/mothership/v1/v2/org suites, packages/db, type-check, lint, check:audits (50) pass. Ops scripts exercised end-to-end against a throwaway local Postgres only.
Checklist