Repository navigation
chore(search): retire legacy search knowledge base projection rows in place - #9511
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
[Medium impact] The reviewed changes appear safe to merge after the old shadow-copy job is aborted as required by the runbook. SummaryReplaces shadow-copy retirement with an in-place purge of retired Search candidate rows.
|
There was a problem hiding this comment.
All reported issues were addressed across 22 files
This PR changes a database schema or migrates data. Ultrareviews find 2.4x more serious bugs than standard reviews. Comment @cubic-dev-ai ultrareview to run one.
Turn on auto-fix | Re-trigger cubic
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
… projection function - Re-check the session advisory lock inside every purge batch: the client reconnects silently after a dropped connection, and the new backend does not hold the old one's lock - Build the purge client without the sslmode/sslrootcert URL parameters, enforcing them as ssl verify-full; postgres.js forwards sslrootcert as a startup parameter the server rejects - Pin the purge connection's search_path to public, pg_temp - Reinstall sync_embedding_search() on a dev push that already recorded 0016, since push runs no versioned migration
A Search knowledge base's chunk writes now delete its candidate rows, so an explicit vector search of one finds nothing; hybrid search still decides access on the document
…fter staging's 0448
f386125 to
ae18bda
Compare
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
…le id A concurrent update could move every chosen row to a new tuple id before the delete, so the batch deleted nothing and the purge reported the knowledge base finished with rows left. The batch now locks its rows in one statement and deletes them in the next, whose snapshot sees the current versions
|
@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 24 files
You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Turn on auto-fix | Re-trigger cubic
|
@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.
No issues found across 24 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Turn on auto-fix | Re-trigger cubic
- --execute checks that public.sync_embedding_search has the retiring body and its embedding_search_sync trigger is enabled; before that, chunk writes keep projecting the rows a purge deletes. The dry run reports the same check - One whitespace-insensitive matcher for the live function source, shared by the preflight and the integration parity tests; drop the unit test that compared the migration file text - --help adds the rebuild precautions: wait out an anti-wraparound autovacuum, bound maintenance_work_mem, clean up a failed concurrent reindex
|
@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 23 files
You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Turn on auto-fix | Re-trigger cubic
…he retiring function - embedding_search_sync must be enabled for ordinary writes (origin or always, not replica-only) and call public.sync_embedding_search - Drop the redundant client port option; postgres.js reads the URL port
|
@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.
No issues found across 23 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
You've manually re-run cubic several times on this PR. Each manual re-review checks the full PR again and counts toward your usage quota. To preserve your usage limits, we recommend letting cubic automatically review new commits.
Turn on auto-fix | Re-trigger cubic
Summary
retire-indexed-search.ts) can't practically finish:CREATE OR REPLACE FUNCTION sync_embedding_search().is_search_index) now deletes that chunk's candidate row instead of projecting it.INTO STRICT, 512-prefix rule and upsert.embedding_search_synctrigger, its WHEN guard, the source/ACL trigger and the FK cascade are unchanged.workspace-kb-document-access.integration.tsnow asserts this.SYNC_EMBEDDING_SEARCH_FUNCTIONinknowledge-projection.ts. Script migration 0016, and so fresh databases anddb:push, install the same body. An integration test keeps the provisioned and 0449-installed bodies identical to it, through the same whitespace-insensitive matcher (isCurrentSyncEmbeddingSearchSource) the purge preflight uses.db:pushon a database that already recorded 0016 skips the backfill but still reinstalls the function, because push runs no versioned migration.db:purge-search-projection:--executedeletes Search-KB candidate rows in bounded batches throughembedding_search_kb_idx, deleting by ctid. Each batch locks its rows (FOR UPDATE) in one statement and deletes them in the next, so a concurrent update cannot move them away and leave a falsely empty batch. Each batch is its own short transaction under statement and lock timeouts, with aFOR SHAREre-check ofis_search_index.search_pathtopublic, pg_temp. Requiressslmode=verify-full&sslrootcert=systemin the URL, but enforces them asssl: 'verify-full'and removes them before connecting. postgres.js otherwise forwardssslrootcertas a startup parameter, and the server refuses the connection (42704), which kept the old CLI from ever connecting.--executeuntil migration 0449 is live: the livepublic.sync_embedding_searchbody must match the constant, and theembedding_search_synctrigger must fire for ordinary writes (not disabled or replica-only) and call that function.embeddingordocument.db:pushkeeps its migration fence.Merge order: merge only after the stalled shadow-copy job has been aborted with the current release's tool. This PR deletes that tool.
Operator runbook
--executerefuses until migration 0449 is live, and the dry run reportsprojectionRetired.db:purge-search-projectiondry run: confirmprojectionRetired: trueand that the listed knowledge bases are the retired Search ones.--execute --max-batches <n>first, watching database latency, CPU, replica lag and WAL. Then rerun until the dry run reports none remaining.pg_stat_activityfor an anti-wraparound autovacuum of the table (query LIKE '%embedding_search%(to prevent wraparound)%'), and wait while one runs.DROP INDEX CONCURRENTLY embedding_search_512_cosine_hnsw_idx_ccnew;and retry. Only the 512 HNSW index needs rebuilding: the retired Search knowledge bases usetext-embedding-3-small, whose chunks project onlyvector_512. In rehearsal a largermaintenance_work_memwas OOM-killed, which is why the setting above is lower.Rehearsal timings on a production-sized copy: purge ~27 min (batch p50 0.65s), REINDEX 30+ min, VACUUM ~5–6 min.
Type of Change
Testing
packages/db/scripts/purge-search-projection.integration.ts(9 tests, green locally on Postgres 17 + pgvector):--executerefuses, deleting nothing, while the old function body is installed or the trigger is disabled, replica-only or calling another function, and proceeds once 0449 is applied. The dry run reports the same check.search_pathpointing at a shadow schema.sslrootcert/sslmodestartup parameter and usesssl: 'verify-full'.search_pathpin,sslrootcertremoval, dev-push function refresh) turns its test red.push.integration,knowledge-projection.integrationandsearch-index.integrationpass locally.check:migrations,drizzle-kit generate(no changes),bun run lint,check:audits, block registry check and type-check pass. The full test suite runs in CI.Checklist
test-auditauthoring gate)