# 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` — именование и доставка артефактов