From f90a91b6c5d68756a8b350cabc656359196d593c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Wed, 17 Jun 2026 17:37:54 +0400 Subject: [PATCH] =?UTF-8?q?session-07:=20=D1=87=D0=B0=D0=BD=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D1=8F=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA?= =?UTF-8?q?=D0=B0,=20worker'=D1=8B,=20=D0=BE=D0=B4=D0=BD=D0=BE=20DB-=D1=81?= =?UTF-8?q?=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History/session-07-chunks.md | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 History/session-07-chunks.md diff --git a/History/session-07-chunks.md b/History/session-07-chunks.md new file mode 100644 index 0000000..63feff9 --- /dev/null +++ b/History/session-07-chunks.md @@ -0,0 +1,79 @@ +# Сессия #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` как узкое место.