Files
contracts/History/sonnet-question-sqlite-2026-07-15.md
T

3.2 KiB
Raw Blame History

Вопрос для Sonnet (без ссылок на файлы)

Контекст

Мигрировали сервис "Сверка Договоров" с ВМ на Flask (managed Python, Штурвал). Код готов — 22 эндпоинта, вся логика внутри Flask:

  • upload (XHR + progress), unzip, convert-doc
  • классификация (LLM, ThreadPoolExecutor внутри Flask-потока для >10 файлов)
  • группировка
  • сравнение через SSE с heartbeat
  • CRUD документов, supplements, промптов
  • чат с LLM по результатам спецификации

Архитектура: db/ (чистый CRUD) → services/ (бизнес-логика) → routes/ (Flask blueprints).

Проблема

Сейчас БД — PostgreSQL. Но данные ВРЕМЕННЫЕ:

  • При загрузке страницы cleanup() → DELETE ALL из всех таблиц (кроме prompts)
  • Юзер загрузил файлы → обработал → закрыл → данные не нужны
  • Файлы хранятся как base64 в БД (конфиденциально, должны умереть с сессией)

Поднимать отдельный PostgreSQL-сервис в кластере ради временных данных — overkill.

Предложение

Заменить PostgreSQL на SQLite (stdlib sqlite3):

  • База — файл /tmp/contracts.db внутри Flask-контейнера
  • connection.py переписать (~80 строк), db/*.py — мелкие правки (~30 строк)
  • Остальной код (services, routes) — без изменений
  • cleanup → os.remove() — атомарно, никаких DELETE, данные гарантированно исчезли
  • Упал контейнер → файл исчез

Детальнее про конкурентность

В НАШЕЙ архитектуре:

  1. Classify запускается ВНУТРИ Flask-процесса как daemon-поток (threading.Thread), НЕ отдельный процесс
  2. ThreadPoolExecutor(max_workers=4) внутри classify — 4 потока шлют запросы к LLM API
  3. SSE-стриминг — читает БД, один writer (classify), один reader (SSE)
  4. Обычно classify синхронный (≤10 файлов) — вообще один поток

То есть: ОДИН процесс Flask, несколько потоков. Несколько процессов нет.

Что меняется в коде

connection.py:

  • psycopg2.pool → sqlite3 с thread-local соединениями
  • threading.local() + get_conn() на каждый поток
  • PRAGMA journal_mode=WAL
  • check_same_thread=False

db/*.py:

  • %s → ? (sqlite-стиль placeholders)
  • RETURNING * → lastrowid + отдельный SELECT
  • ::jsonb → json.dumps()
  • BOOLEAN → INTEGER (0/1)

Остальное без изменений.

Вопрос

Есть ли подводные камни с SQLite для этой конкретной архитектуры (один процесс, несколько потоков, WAL, thread-local connections)?