Files
contracts/History/session-07-chunks.md

80 lines
3.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Сессия #7 — чанковая загрузка, worker'ы, одно соединение
_Дата: 2026-06-17_
_Версия: v1.15 → v1.18_
---
## Проблема
Загрузка PDF 153 KB падала с «✗ Сеть»:
- v1.14: прямая загрузка (один POST) → Ingress режет `client_max_body_size`
- v1.15-16: чанки 50KB в памяти `_chunk_store = {}` → worker'ы разные, чанки теряются
- v1.17: чанки в PostgreSQL (таблица `chunks`) → всё равно «Сеть»
- v1.18: ОДНО DB-соединение на сборку → ?
## Хронология
### v1.14: прямая загрузка
`POST /` с файлом 153 KB → Ingress (nginx) обрывает → `XHR onerror` → «Сеть»
### v1.15: чанки 50KB в памяти
`POST /chunk` × 3. `_chunk_store = {}` в памяти модуля.
**Ошибка:** dict живёт в одном worker'е. Gunicorn с >1 worker → чанки на разных процессах → второй не видит первый → обрыв.
### v1.16: try/except + проверка doc_id
Добавлена обработка ошибок при сборке. **Откачено** (не решило проблему worker'ов).
### v1.17: чанки в БД
Таблица `chunks(upload_id, chunk_index, chunk_data, ...)`. `ON CONFLICT DO NOTHING`.
**Всё равно «Сеть»** — worker'ы больше не проблема, но осталась другая.
### v1.18: одно DB-соединение (текущая)
**Диагноз:** `_chunk_upload` при сборке делал до 7 отдельных `db.execute`/`db.query`
каждое = новый `psycopg2.connect`. На managed-платформе это медленно → таймаут Ingress → обрыв.
**Исправление:**
- `_save_file_to_db(filename, file_bytes, mime, contract_id, conn=None)` — принимает соединение
- `_chunk_upload` открывает ОДНО соединение на всю сборку:
- SELECT chunks
- INSERT contracts (если нужно)
- INSERT documents
- SELECT id документа
- INSERT supplements
- DELETE chunks
- Все 6 запросов в одной транзакции, одно подключение.
---
## Архитектура чанков (текущая)
```
Клиент: file.slice(0,50KB) → XHR POST /chunk
file.slice(50KB,100KB) → XHR POST /chunk
file.slice(100KB,150KB) → XHR POST /chunk
Сервер /chunk:
1. INSERT INTO chunks (...) ON CONFLICT DO NOTHING ← 1 conn
2. SELECT COUNT(*) FROM chunks ← 1 conn
3. Если received == total_chunks:
ОДНО соединение:
SELECT chunk_data ORDER BY chunk_index
SELECT metadata
INSERT INTO contracts (если нет cid)
COMMIT
→ _save_file_to_db(conn=...)
INSERT INTO documents
SELECT id
INSERT INTO supplements
COMMIT
DELETE FROM chunks
ОТВЕТ {"contract_id": "..."}
```
## Выученные уроки
1. **`_chunk_store` в памяти не работает с несколькими worker'ами** — нужна общая БД.
2. **Много отдельных `db.execute` = много `psycopg2.connect`** — на managed-платформе медленно.
3. **Всегда одно соединение для зависимых операций** — сборка + сохранение должны быть атомарны.
4. **Анализ агентом помог** — указал на `_save_file_to_db` как узкое место.