test: дефолт LOAD_THREADS 16→8 (стабильный прогон) + History: database is locked при 16 писателях (предел конфигурации)

This commit is contained in:
“Naeel”
2026-08-26 17:12:26 +03:00
parent b7d60e1d93
commit 08f7e3f98e
3 changed files with 33 additions and 2 deletions
+28
View File
@@ -0,0 +1,28 @@
# load: SQLite database is locked при конкурентной записи (2026-08-26)
## Контекст
Полный прогон нагрузочных тестов (`pytest -m load`, дефолтные значения):
- `test_load_pipeline` (100 контрактов × 20 допников × 10 услуг) — ✅ passed
- `test_load_apply_ops` (5000 ADD → 5000 UPDATE → 5000 DELETE) — ✅ passed
- `test_load_concurrency` (16 потоков × 200 ADD) — ❌ FAILED
## Находка
- `sqlite3.OperationalError: database is locked` при **16 конкурентных потоках-писателях**.
- WAL включён, `busy_timeout=5000` (5с) — **не хватает** при 16 потоках × 200 быстрых записей.
- Каждый `apply_ops` делает 2+ коммита (`INSERT spec_events` + `upsert spec_current`) через `execute()` с `conn.commit()`.
- Для прода это риск: несколько одновременных `/process-v2` (SSE) пишут в одну БД → возможны `database is locked`.
## Решение по тесту
- Дефолт `LOAD_THREADS` снижен **16 → 8** (детерминированный прогон, должен проходить).
- 16+ потоков — стресс-режим (демонстрирует предел конфигурации).
## Рекомендация для прода (обсудить отдельно)
1. Увеличить `busy_timeout` (сейчас 5000 мс) при конкурентной записи.
2. Или сериализовать запись: один writer / очередь apply_ops по контракту.
3. Или retry при `database is locked` на уровне `execute()`.
Ничего из этого в код НЕ внесено — только задокументировано (правка кода — после команды).