Files
contracts-flask/History/2026-08-27-classify-stuck-at-68.md
T
“Naeel” 475efefb40
Deploy contracts-flask / validate (push) Canceled after 0s
Preserve ZIP source during upload
2026-08-27 09:45:54 +03:00

84 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Классификация застряла на 68/84: диагностика 2026-08-27
## Наблюдение
На экране классификация остаётся на `68/84`, хотя контейнер продолжает работать.
Проверка через ВМ:
```text
GET /api/batch-progress?batch=acbdffe5-e3ec-43f4-ab61-84861cac35bd
{"counts":{"classified":68,"garbage":16},"ok":true,"total":84}
```
Повторный запрос вернул то же значение. Kubernetes показывает pod
`pythonk8s-574b5cf9b4-z4wxz` в состоянии `Running`, `Ready 1/1`, `RESTARTS 0`.
Событий Kubernetes нет. На ВМ `contracts.service` активен, `convert_server.py`
запущен в одном экземпляре.
## Причина в коде
`site/routes/api_bp.py` возвращает раздельные счётчики `classified`, `failed` и
`garbage`, а `total` равен числу всех документов батча.
`site/static/app.js` в `runClassify()` считает завершённые документы так:
```javascript
var done = (d.counts.classified || 0) + (d.counts.failed || 0);
```
`garbage` в эту сумму не включён. Для текущего батча:
```text
done = 68 classified + 0 failed = 68
total = 84
garbage = 16
фактически завершено = 68 + 0 + 16 = 84
```
Поэтому условие `done >= total` никогда не выполняется, polling не
останавливается, а кнопка остаётся на `68/84`. Это ошибка фронтендового
подсчёта прогресса, а не зависание Kubernetes или LLM на 68-м файле.
## Исправление
В `site/static/app.js` к числу завершённых документов добавлен конечный статус
`garbage`:
```javascript
var done = (d.counts.classified || 0)
+ (d.counts.failed || 0)
+ (d.counts.garbage || 0);
```
Версия приложения повышена с `2.0.17` до `2.0.18`; cache-buster статических
скриптов обновлён в `site/templates/index.html`.
Kubernetes проверялся только командами чтения через ВМ:
`kubectl get`, `kubectl describe`, `kubectl top`, `kubectl logs`.
## Дополнительная проверка загрузки ZIP
При проверке загрузки разными способами обнаружен отдельный дефект связи
файлов с архивом. `expandZipClient()` создаёт для каждого распакованного файла
поле `zip_source`, а `uploadFile(file, onProgress, zipSource)` умеет передавать
его в `/api/upload_refs`. Однако вызов `uploadFile()` в цикле `onFilesSelected()`
передавал только два аргумента. Поэтому backend получал `zip_source=null`, и
связь с исходным ZIP терялась.
Проверены архивы:
- `testgen/out/zips/duplicates_inside.zip` — целый ZIP, два файла с одинаковым именем;
- `testgen/out/zips/mixed_with_error.zip` — целый ZIP, корректный и повреждённый DOCX.
Исправление применено в `site/static/files.js`: третьим аргументом передаётся
`entry.zip_source`. Для обычных файлов значение `null`, поэтому их поведение не
изменяется. Версия приложения повышена с `2.0.18` до `2.0.19`, cache-buster
обновлён в `site/templates/index.html`.
## Проверки исправления
- `node --check site/static/files.js` — успешно;
- frontend upload-тесты — успешно;
- layer 2 upload-тесты — успешно;
- архивы `duplicates_inside.zip` и `mixed_with_error.zip` прошли `unzip -t`.