fix(ai-vault-search): read the resumed session id off an optional row

This commit is contained in:
Jinwoo-H
2026-09-10 13:16:32 -04:00
parent 62c8228ce6
commit 86c6e39c8f
2 changed files with 5 additions and 28 deletions
@@ -117,7 +117,11 @@ export class SessionSearchIndexWriter {
// cursor worth continuing: it has no session row to hang new rows off, so
// this read makes one. Declining instead would force a whole re-read of
// that file on every pass for as long as it grows.
return this.stage(candidate, existing, mode === 'append' ? existing.session_row_id : null)
return this.stage(
candidate,
existing,
mode === 'append' ? (existing?.session_row_id ?? null) : null
)
}
/** Invalidation hides the generation immediately; cleanup does the expensive deletes later. */
@@ -1,27 +0,0 @@
import { setImmediate as yieldToEventLoop } from 'node:timers/promises'
import type SyncDatabase from '../sqlite/sync-database'
const WARM_ROWS_PER_STEP = 50_000
/**
* Reads the messages table through in slices so its pages sit in the OS cache
* before the first query joins against it. Measured on a 4 GB index: the first
* query after a cold start drops from ~1.3 s to ~0.45 s, and each slice holds
* the connection for under 50 ms.
*/
export async function warmSessionSearchPages(
db: SyncDatabase,
stopped: () => boolean
): Promise<void> {
const max = (db.prepare('SELECT max(id) AS id FROM messages').get() as { id: number | null }).id
const touch = db.prepare(
'SELECT count(*) FROM messages WHERE id BETWEEN ? AND ? AND role IS NOT NULL'
)
for (let low = 1; max !== null && low <= max; low += WARM_ROWS_PER_STEP) {
if (stopped()) {
return
}
touch.get(low, low + WARM_ROWS_PER_STEP - 1)
await yieldToEventLoop()
}
}