Skip to content

Commit e43c5e0

Browse files
committed
improvement(knowledge): leave the legacy keyword backfill unscoped
1 parent 0a4036b commit e43c5e0

4 files changed

Lines changed: 8 additions & 29 deletions

File tree

‎packages/db/script-migrations-paused-billing-attribution.test.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ describe('script migration registry', () => {
377377
'0022_projection_source_acl_backfill',
378378
'0023_projection_acl_skip_unfilled',
379379
'0024_knowledge_projection_async',
380+
'0025_scope_keyword_projections',
380381
])
381382
})
382383
})

‎packages/db/script-migrations/0016_backfill_search_vectors.integration.ts‎

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,9 @@ describe('search projection upgrade in PostgreSQL', () => {
4444
await sql.unsafe(
4545
`ALTER TABLE embedding_search ${fields.map((field) => `DROP COLUMN ${field}`).join(', ')}`
4646
)
47-
/** A workspace holds one search index, so each fixture index has its own. */
48-
await sql`INSERT INTO knowledge_base (id, user_id, name, workspace_id, embedding_model, is_search_index) VALUES
49-
('prefix', 'reader', 'Prefix fixture', 'workspace', 'text-embedding-3-small', true),
50-
('full', 'reader', 'Full fixture', 'full-workspace', 'gemini-embedding-001', true),
51-
('legacy', 'reader', 'Legacy fixture', 'workspace', 'text-embedding-3-small', false)`
47+
await sql`INSERT INTO knowledge_base (id, user_id, name, workspace_id, embedding_model) VALUES
48+
('prefix', 'reader', 'Prefix fixture', 'workspace', 'text-embedding-3-small'),
49+
('full', 'reader', 'Full fixture', 'workspace', 'gemini-embedding-001')`
5250
await backfillEmbeddingSearch(sql)
5351
await sql.unsafe(`INSERT INTO embedding
5452
(id, knowledge_base_id, document_id, chunk_index, chunk_hash, content, content_length, token_count, start_offset, end_offset, embedding)
@@ -155,22 +153,6 @@ describe('search projection upgrade in PostgreSQL', () => {
155153
expect(await backfillSearchKeywords(sql)).toBe(0)
156154
})
157155

158-
it('leaves the chunks of a base that is not a search index unfilled', async () => {
159-
await sql.unsafe(`INSERT INTO embedding
160-
(id, knowledge_base_id, document_id, chunk_index, chunk_hash, content, content_length, token_count, start_offset, end_offset, embedding)
161-
VALUES ('legacy-chunk', 'legacy', 'legacy-document', 0, 'legacy-hash', 'Synthetic fixture', 17, 4, 0, 17,
162-
array_fill(0.01::real, ARRAY[1536])::vector(1536))`)
163-
await sql`DELETE FROM embedding_keyword_search WHERE id = 'legacy-chunk'`
164-
try {
165-
expect(await backfillSearchKeywords(sql)).toBe(0)
166-
expect(
167-
await sql`SELECT id FROM embedding_keyword_search WHERE id = 'legacy-chunk'`
168-
).toHaveLength(0)
169-
} finally {
170-
await sql`DELETE FROM embedding WHERE id = 'legacy-chunk'`
171-
}
172-
})
173-
174156
it('repairs an interrupted index build and preserves valid indexes on replay', async () => {
175157
await expect(
176158
sql.unsafe(

‎packages/db/script-migrations/0016_backfill_search_vectors.ts‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,7 @@ export async function backfillSearchVectors(sql: Sql): Promise<number> {
115115
return count
116116
}
117117

118-
/**
119-
* Keeps keyword scoring independent of the full-vector and chunk-content storage working sets. Only
120-
* search-index chunks are filled: they are the only rows the projection holds once
121-
* `0025_scope_keyword_projections` scopes its triggers, so a rerun cannot refill the rest.
122-
*/
118+
/** Keeps keyword scoring independent of the full-vector and chunk-content storage working sets. */
123119
export async function backfillSearchKeywords(sql: Sql): Promise<number> {
124120
await sql.begin(async (tx) => {
125121
await tx.unsafe("SET LOCAL lock_timeout = '5s'")
@@ -163,7 +159,6 @@ export async function backfillSearchKeywords(sql: Sql): Promise<number> {
163159
), batch AS MATERIALIZED (
164160
SELECT e.id, e.knowledge_base_id, e.document_id, e.enabled, e.content_tsv
165161
FROM missing m INNER JOIN embedding e ON e.id = m.id
166-
INNER JOIN knowledge_base k ON k.id = e.knowledge_base_id AND k.is_search_index
167162
ORDER BY e.id FOR KEY SHARE OF e
168163
), inserted AS (
169164
INSERT INTO embedding_keyword_search (id, knowledge_base_id, document_id, enabled, content_tsv)

‎packages/db/script-migrations/0025_scope_keyword_projections.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ async function installDocumentTrigger(tx: TransactionSql): Promise<void> {
117117
* whichever mode runs. The document trigger stops firing on inserts and on updates that change
118118
* nothing it carries.
119119
*
120-
* Rows already written for other bases are left in place: removing them is a table owner's
121-
* maintenance, not a deploy's. All of it is installed in one transaction, so no marker change sees
120+
* Rows already written for other bases, and those a rerun of `0016_backfill_search_vectors` writes
121+
* before this reruns after it, are left in place: nothing reads them, and removing them is a table
122+
* owner's maintenance, not a deploy's. All of it is installed in one transaction, so no marker change sees
122123
* the scoped chunk trigger without the base trigger that backfills it. Each attempt waits at most
123124
* {@link TRIGGER_LOCK_TIMEOUT} for the trigger DDL's locks and is retried within the budget.
124125
* Idempotent.

0 commit comments

Comments
 (0)