Files
drhider/History/infra/2026-08-24-upload-logic-schema.md
T

6.6 KiB
Raw Blame History

Схема логики загрузки + найденные баги/несоответствия (2026-08-24)

infra. Подробная схема по коду: index.html (фронт), api_bp.py, session.py, obfuscator.py, extractor.py.

Участники

  • Браузер — index.html: выбор файлов/папки, PUT на ВМ, SSE-прогресс, статусы.
  • ВМ-буфер — nginx dav https://contracts.kube5s.ru/drhider-upload/ (CORS разрешён только для origin https://drhider.pythonk8s.dev.nubes.ru).
  • Бэк — Flask (api_bp.py): upload_refs (pull), process_stream (SSE, воркер-поток), session.py (лимиты), drhider (extractor→scanner→replacer→builder).

Этап 0 — выбор файлов (браузер)

  1. fileInput (multiple, accept) — для .ziplistZipFiles (раскрытие в браузере, allowedExt = .pdf .doc .docx .txt .md) → addFileWithDedup; иначе — как есть.
  2. folderInput (webkitdirectory) — рекурсивно: webkitRelativePath.slice(1) (отбрасываем верхнюю папку), zip раскрывается с префиксом пути, документы — с относительным путём, прочее — пропуск.
  3. addFileWithDedup: дедуп (имя+размер → пропуск; коллизия имени → суффикс _2); лимиты 50МБ/файл и 500МБ/сессия → overNames🔥 не учитывается» в обычной таблице).

Этап 1 — загрузка (uploadFiles, фаза 1)

  1. toSend = файлы БЕЗ overNames; over-файлы сразу получают статус «пропущен (лимит)» (v0.0.71).
  2. Для каждого файла: PUT на VM_UPLOAD_URL + token + '_' + k (имя в URL не несётся) → прогресс % в ячейке → ✓ N KB/s. refs.push({name, size, url}). Таймаут 300с.
  3. POST /api/upload_refs {session, files: refs}:
    • бэк: для каждого ref: size > 50МБ → delete+skip; GET url (pull egress, timeout 120с) → content; content > 50МБ → delete+skip; add_file(sid, name, content) (лимит сессии 500МБ); delete url с ВМ.
    • ошибка сети/DNS → 502 «Pull failed» (весь запрос падает).
  4. Тест-режим ?upload-only=1 — стоп после фазы 1.

Этап 2 — обработка (SSE, фаза 2)

  1. EventSource /api/process_stream/<sid>; воркер-поток → obfuscate_files(all_files).
  2. obfuscator (проход 1): expand_zips (повторная распаковка zip, basename, защита от бомб) → _dedupe_file_names → для каждого: extract_text (исключение → skipped, событие done на этапе извлечения) → scan_regexextract_done (total_chars, per_file) → scan_llm_ner (чанки: file_start/file_chunk/file_done; отмена → CancelRequested).
  3. проход 2: apply_replacements для каждого (битые/скан → пропуск; при отмене — только llm_done) → donebuild_zip + build_mapping_csv → событие result/cancelled.
  4. Фронт: 3-секционная таблица (Обработанные / Текущий / Ожидают); статусы: done (до extract_done = битый → skipped «не извлечён» v0.0.71), current, analyzed, pending; complete/cancelled → статистика, кнопки ZIP/CSV, заморозка сессии.

Найденные баги и несоответствия

  1. [исправлено v0.0.71] Статус «пропущен» использовался для ДВУХ разных причин: лимит и «не извлёкся». Теперь: «пропущен (лимит)» и «не извлечён» (пустой/битый/скан).
  2. [исправлено v0.0.71] over-файлы во время обработки попадали в группу «Ожидают обработки» (нет procState → pending) с оценкой времени. Теперь — отдельная группа « Пропущены (сверх лимита)».
  3. [открыто] upload_refs неатомарен: при ошибке pull (DNS/сеть) часть файлов уже добавлена в сессию и удалена с ВМ, но фронт получает 502 и бросает — сессия-сирота, файлы на ВМ частично остаются (инцидент 18:42). Нужны ретраи/атомарность.
  4. [открыто] upload_refs при превышении суммарного лимита сессии отвечает «Session not found» (404) — add_file возвращает False и для отсутствия сессии, и для лимита; сообщение неверное.
  5. [открыто, риск] Повторный expand_zips на бэке (с os.path.basename — обрезает пути) при отправке zip как есть (v0.0.69) ломает соответствие idx: количество файлов бэка ≠ фронта → sendIdx[d.idx] = undefined. Обычно не срабатывает (фронт сам раскрывает), но риск при расхождении allowedExt.
  6. [открыто] allowedExt не совпадают: фронт раскрывает из zip только документы, бэк expand_zips берёт ВСЕ файлы (без фильтра) — расхождение поведения при zip «как есть».
  7. [открыто, косметика] Счётчик «Добавлено из папки: N» завышается при дедупе (added++ безусловно после addFileWithDedup).
  8. [открыто] Три разных отображения одной причины (лимит) до обработки / при старте / в обработке — унифицировано в v0.0.71 (группа over).

Проверка

  • node --check — OK, py_compile — OK.
  • Локально (v0.0.71): группа « Пропущены (сверх лимита)» + «пропущен (лимит)» — работает. Полный цикл локально невозможен из-за CORS ВМ-буфера (разрешён только origin прода).
  • Версия 0.0.70 → 0.0.71.