From af4d0f353bd496146d6d80b2e1a8827760edfe19 Mon Sep 17 00:00:00 2001 From: Michael Chus Date: Sun, 1 Mar 2026 18:22:42 +0300 Subject: [PATCH] Add batch file upload ADR contract Co-Authored-By: Claude Sonnet 4.6 --- rules/patterns/batch-file-upload/contract.md | 101 +++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 rules/patterns/batch-file-upload/contract.md diff --git a/rules/patterns/batch-file-upload/contract.md b/rules/patterns/batch-file-upload/contract.md new file mode 100644 index 0000000..c896ee5 --- /dev/null +++ b/rules/patterns/batch-file-upload/contract.md @@ -0,0 +1,101 @@ +# Contract: Batch File Upload + +Version: 1.0 + +## Purpose + +ADR: стратегия загрузки большого числа файлов через multipart-запросы +без переработки серверного pipeline и без скрытых лимитов. + +--- + +## ADR + +**Дата:** 2026-03-01 +**Статус:** Accepted + +### Контекст + +Клиент должен загрузить список файлов на сервер для обработки. +Загрузка всех файлов одним multipart-запросом упирается в скрытые лимиты: +количество parts, размер тела запроса (413), таймауты соединения. +Переработка серверного pipeline под стриминговую загрузку — отдельная дорогостоящая задача. + +### Решение + +Клиент делит список файлов на батчи фиксированного размера и отправляет каждый батч +отдельным multipart-запросом. + +- Размер батча определяется константой `MAX_FILES_PER_BATCH` (выбирается проектом). +- Батчи считаются по **числу файлов**, не только по байтам. +- Обработка батчей **последовательная** по умолчанию. + Параллельная обработка допускается только если явно оговорена и задокументирована. +- Каждый батч производит отдельный downloadable артефакт, + либо агрегируется на финальном шаге — решение принимается на уровне проекта. + +### Последствия + +**Плюсы:** +- Избегаем скрытых лимитов на количество multipart parts +- Снижаем риск таймаутов и ошибок 413 +- Не требует немедленной переработки серверного parser pipeline + +**Минусы:** +- Больше round-trips (N батчей = N запросов) +- Несколько выходных файлов если артефакты не агрегируются +- Более долгий end-to-end UX для пользователя + +--- + +## Правила реализации + +### Константа батча + +```go +const MaxFilesPerBatch = 1000 // выбирается проектом +``` + +Константа объявляется явно — не хардкодится inline. + +### Именование артефактов + +Результаты батчей именуются с суффиксом `_partN`: + +``` +report_part1.csv +report_part2.csv +report_part3.csv +``` + +Или агрегируются в единый файл на финальном шаге — тогда суффикс не нужен. + +### Обработка ошибок + +- Ошибку превышения лимита parts (`multipart: too many parts`) **не маскировать** под ошибку размера. +- Логировать первичную причину с явным указанием типа лимита. +- Клиент при получении ошибки лимита должен уменьшить батч и повторить, либо сообщить пользователю. + +```go +// Правильно +log.Error("batch upload failed: multipart parts limit exceeded", "batch", batchNum, "files", len(batch)) + +// Неправильно +log.Error("batch upload failed: file too large") // маскирует причину +``` + +### UI + +UI обязан показывать пользователю: + +- Общее количество батчей (проходов): `Шаг 2 из 5` +- Прогресс текущего батча: прогресс-бар или процент +- Финальный статус каждого батча до начала следующего + +Пользователь не должен видеть технический термин "батч" — использовать "шаг" или "проход". + +--- + +## Связанные контракты + +- `go-background-tasks` — каждый батч запускается как фоновая задача +- `import-export` — именование и доставка артефактов