Skip to content

fix: serialise RAG indexing writers (RC5 — close concurrent SQLITE_BUSY path)#15

Merged
ipiton merged 2 commits into
mainfrom
bugfix/rag-index-writer-serialization
May 23, 2026
Merged

fix: serialise RAG indexing writers (RC5 — close concurrent SQLITE_BUSY path)#15
ipiton merged 2 commits into
mainfrom
bugfix/rag-index-writer-serialization

Conversation

@ipiton

@ipiton ipiton commented May 23, 2026

Copy link
Copy Markdown
Owner

Follow-up к #14 (0.8.4). Закрывает последний путь конкурентной записи в vectors.db.

Проблема (RC5)

server.callIndexDocuments зовёт Engine.IndexDocuments напрямую, минуя guard indexWithLock (re.indexing), которым пользуются только startup и file_watcher. Значит ручной index_documents и фоновый watcher-индекс могли писать в vectors.db одновременно. Фикс 0.8.4 (per-connection busy_timeout) делает их вежливой очередью до 5с, но при тяжёлом индексе с write-txn >5с SQLITE_BUSY оставался возможен.

Фикс

IndexDocuments держит выделенный Engine.indexMu sync.Mutex на всё время записи → любые indexing-прогоны сериализованы независимо от вызывающего.

  • re.indexing оставлен как есть — он коалесцирует дебаунс-тики watcher'а, чтобы они не стекались.
  • Семантика foreground сохранена: ручной вызов ждёт на indexMu и реально индексирует, а не «пропускается».
  • Дедлока нет: re.mu освобождается до вызова IndexDocuments, indexMu независим.

Тест

TestIndexDocumentsSerialisesWriters — детерминированный: держим indexMu → второй IndexDocuments обязан блокироваться (150ms окно) → после release отрабатывает без ошибки. Проходит под -race.

Проверено

  • go build ./..., go vet ./internal/rag/..., go test ./... (+ ./internal/rag/... -race) — всё зелёное.

См. 06-planning/2026-05-05-sqlite-busy-incident.md §7 RC5 (помечен FIXED).

ipiton added 2 commits May 23, 2026 22:06
callIndexDocuments invoked Engine.IndexDocuments directly, bypassing the
indexWithLock guard (re.indexing) that only the startup and file-watcher paths
used. A manual index_documents and a background watcher index could therefore
write to vectors.db concurrently. The 0.8.4 per-connection busy_timeout made
them queue up to 5s, but a heavy index holding a write transaction longer than
that could still return SQLITE_BUSY.

Hold a dedicated Engine.indexMu for the whole IndexDocuments duration so every
indexing run is serialised regardless of caller. The watcher's `indexing` flag
is kept (it coalesces debounced ticks); foreground callers wait on the mutex
and index for real instead of being skipped. Regression test asserts a second
call blocks while the lock is held and completes once released.
@ipiton ipiton merged commit 16ad000 into main May 23, 2026
1 check passed
@ipiton ipiton deleted the bugfix/rag-index-writer-serialization branch May 23, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant