PageIndex/pageindex
mountain 890b520b1c fix(sqlite): make concurrent indexing writes robust (no "database is locked")
Real concurrency e2e (8 threads adding the same file) surfaced a bug the
mocked unit tests missed: concurrent add_document calls failed with
sqlite3.OperationalError "database is locked". Root cause — under WAL the
dedup SELECT (find_document_by_hash) left a read snapshot on the
connection, and the subsequent INSERT on that stale snapshot raised
SQLITE_BUSY_SNAPSHOT, which busy_timeout does not retry.

Fixes:
- open connections in autocommit (isolation_level=None) so a SELECT never
  leaves a lingering read snapshot and each write is its own transaction
- PRAGMA busy_timeout=10000 so concurrent writers wait for the WAL
  single-writer lock instead of failing immediately
- an instance-level write lock serializing the fast write methods within
  the process (the expensive LLM indexing stays parallel)

Now 8 concurrent adds of one file -> a single doc_id, zero errors.
Adds a real-thread regression test.

Claude-Session: https://claude.ai/code/session_01Kx5DgKbhK1N8autqXH8SmS
2026-07-07 18:23:01 +08:00
..
backend style(cloud): annotate best-effort response-close in query_stream cleanup 2026-07-07 16:02:33 +08:00
index merge upstream/main into dev; port #188 into the index pipeline 2026-07-07 16:34:02 +08:00
parser refactor(sdk): typed returns, protocol contract, parser layering 2026-07-07 12:15:34 +08:00
storage fix(sqlite): make concurrent indexing writes robust (no "database is locked") 2026-07-07 18:23:01 +08:00
__init__.py fix: load .env explicitly in pageindex __init__ 2026-07-07 17:00:34 +08:00
agent.py fix: resolve five P1 defects from the SDK review 2026-07-07 10:12:51 +08:00
client.py refactor(sdk): typed returns, protocol contract, parser layering 2026-07-07 12:15:34 +08:00
cloud_api.py fix(cloud_api): restore legacy is_retrieval_ready swallow-on-error contract 2026-07-07 15:48:49 +08:00
collection.py refactor(sdk): typed returns, protocol contract, parser layering 2026-07-07 12:15:34 +08:00
config.py fix(llm): configurable per-call litellm params instead of mutating the global 2026-06-25 17:09:43 +08:00
errors.py fix(cloud): align cloud/local backend contracts and harden the HTTP layer 2026-07-07 09:40:09 +08:00
events.py feat: add PageIndex SDK with local/cloud dual-mode support (#207) 2026-04-08 20:21:58 +08:00
page_index.py refactor(index): dedupe the copied indexing pipeline behind deprecation shims 2026-07-07 10:42:23 +08:00
page_index_md.py refactor(index): dedupe the copied indexing pipeline behind deprecation shims 2026-07-07 10:42:23 +08:00
retrieve.py refactor(index): dedupe the copied indexing pipeline behind deprecation shims 2026-07-07 10:42:23 +08:00
tokens.py refactor(sdk): typed returns, protocol contract, parser layering 2026-07-07 12:15:34 +08:00
types.py refactor(sdk): typed returns, protocol contract, parser layering 2026-07-07 12:15:34 +08:00
utils.py refactor(index): dedupe the copied indexing pipeline behind deprecation shims 2026-07-07 10:42:23 +08:00