Files
mostovik-backend/docs/source-record-export-matrix-ru.md
Aleksandr Meshchriakov b19951d0c9
All checks were successful
CI/CD Pipeline / Quality Gate (push) Successful in 43s
CI/CD Pipeline / Build and Push Images (push) Successful in 19s
CI/CD Pipeline / Internal Notify (push) Successful in 0s
CI/CD Pipeline / Deploy Dev via Compose (push) Successful in 24s
feat: align source data and nightly exports
2026-08-03 19:27:07 +02:00

6.6 KiB
Raw Blame History

Матрица файловых выгрузок источников

Пользовательский контракт

Frontend отправляет администраторский POST /api/v2/organization-source-records/export-ticket/ с массивом sources и выбранным format. В ответ он получает короткоживущий одноразовый ticket и передаёт его обычной HTML-формой в POST /api/v2/organization-source-records/export-download/. Поэтому браузер сохраняет потоковый ZIP напрямую на диск, не удерживая весь архив как Blob в JavaScript. Ticket передаётся в теле формы, не попадает в URL и после первого запроса становится недействительным.

Совместимый администраторский POST /api/v2/organization-source-records/export/ по-прежнему сразу возвращает тот же ZIP API-клиентам. Крупный XLSX может состоять из нескольких файлов *-part-001.xlsx, *-part-002.xlsx и далее.

При скачивании endpoint не читает таблицы записей источников и не строит CSV, XLSX или JSON заново. Он упаковывает файлы последнего полностью опубликованного ночного поколения и сразу потоково отправляет ZIP без временной копии всего архива. Поэтому Content-Length у ответа отсутствует. Если ни одного поколения ещё нет, API отвечает 503 с кодом source_export_not_ready.

Матрица

Группа API Файл CSV XLSX JSON
financial_indicators financial-indicators да
government_procurements public-procurements да да да
industrial_production manufacturers-and-products да да да
planned_inspections planned-inspections да да да
bankruptcy bankruptcy-procedures да да да
defense_suppliers defense-unreliable-suppliers да да да
arbitration arbitration-cases да да да
security_registries information-security-registries да да да
vacancies labor-vacancies да да да

Итого формируется 25 логических артефактов: один JSON для финансовых показателей и по три формата для остальных восьми групп. Физических файлов может быть больше из-за разбиения крупных XLSX. Если финансовые показатели выбраны вместе с другим форматом, в ZIP для них всё равно включается JSON.

Ночная генерация

Celery Beat запускает organizations.tasks.refresh_source_record_export_artifacts ежедневно в 05:30 Europe/Moscow, после ежедневного обновления organization sources в 04:30.

Генератор:

  1. читает каждую группу из БД один раз без глобальной сортировки миллионов строк;
  2. пишет compact JSON-массив на диск и использует его как готовый JSON без второй копии;
  3. потоково создаёт CSV и XLSX без накопления всех строк в памяти;
  4. разбивает XLSX по умолчанию по 100 000 строк на отдельные файлы, ограничивая временный XML и не превышая лимит Excel;
  5. записывает размеры файлов и номера частей в manifest;
  6. атомарно переключает current.json только после готовности всей матрицы;
  7. сохраняет текущее и предыдущее поколения по умолчанию.

При ошибке незавершённое поколение удаляется, а download endpoint продолжает отдавать предыдущую успешную версию.

Расчёт диска

Атомарная публикация требует одновременно хранить уже опубликованные поколения и одно новое поколение в staging. Минимальный запас под артефакты рассчитывается как (SOURCE_RECORD_EXPORT_GENERATIONS_TO_KEEP + 1) * размер поколения, плюс рабочий запас файловой системы. На снимке dev от 2026-08-03 одно поколение заняло 16,55 ГБ (54 физических файла), поэтому при значении 2 следует выделить не менее 55 ГБ свободного места под каталог выгрузок. Временная копия целого ZIP при скачивании не создаётся.

Хранение и первый запуск

Каталог задаётся через SOURCE_RECORD_EXPORT_DIRECTORY, по умолчанию — media/source-record-exports. Он должен быть общим read-write volume для web и Celery worker. В Docker Compose используется ./media:/app/media.

После первого развёртывания готовое поколение можно создать сразу, не ожидая ночного расписания:

PYTHONPATH=src uv run python src/manage.py build_source_record_exports

Доступные настройки:

Настройка Значение по умолчанию Назначение
SOURCE_RECORD_EXPORT_DIRECTORY media/source-record-exports Общий каталог артефактов
SOURCE_RECORD_EXPORT_GENERATIONS_TO_KEEP 2 Число сохраняемых успешных поколений
SOURCE_RECORD_EXPORT_LOCK_TTL_SECONDS 21600 TTL распределённой блокировки Celery
SOURCE_RECORD_EXPORT_XLSX_ROWS_PER_FILE 100000 Максимум строк данных в одной XLSX-части
SOURCE_RECORD_EXPORT_DOWNLOAD_TICKET_TTL_SECONDS 300 Срок действия одноразового browser-download ticket