diff --git a/dev/README.md b/dev/README.md index 0b94c19..e46fffb 100644 --- a/dev/README.md +++ b/dev/README.md @@ -182,9 +182,8 @@ poll() { # poll <секунд> — статус задания $JOB раз в } ``` -Рецепт прогнан дословно при уже существовавшей в БД строке `legal_entity` с ИНН `7700000001`, поэтому ветка вставки -(без конфликта по `inn`) на чистой БД не выполнялась; `on conflict (inn) do nothing` рассчитан на оба случая, но первая -вставка на пустой БД отдельно не проверялась. +Рецепт прогнан дословно на чистой БД (вставка `legal_entity` без конфликта по `inn`) и повторно при уже существующей +строке (`on conflict (inn) do nothing`); оба пути проверены. Ключ исходника — `uploads/{file_id}/{job_id}/{имя}` (`../context/03-architecture.md`, «Схема ключей S3»). Сообщения на шине можно смотреть параллельно: `docker run --rm --network arm-ka_default natsio/nats-box:0.17.0 nats sub -s @@ -217,17 +216,32 @@ new_job image PDF ocr/aep_5.PDF && poll 30 # 02:12:29 processing # 02:12:34 error INVALID_DOCUMENT dmc ls local/arm-ka/raw/ -# [2026-10-04 02:12:34 UTC] 588B STANDARD 46b0c90b-5a1b-4ac0-9e8a-0cdad80d857e.json -dmc cat "local/arm-ka/raw/$JOB.json" # {"file_uid": "", "error": {"code": "INVALID_DOCUMENT", "message": "Не удалось определить тип документа."}, "data_ocr": {…}} +# [2026-10-04 11:23:58 UTC] 600B STANDARD 0ea16933-4cc1-4b50-bda9-a97089a918c5.json +dmc cat "local/arm-ka/raw/$JOB.json" # {"job_id": "", "files": [{"name": ".json", "response": {"file_uid": "", "error": {"code": "INVALID_DOCUMENT", "message": "Не удалось определить тип документа."}, "data_ocr": {…}}, "parse_error": null}]} ``` -Код `INVALID_DOCUMENT` здесь — **настоящий ответ ИС из фикстуры**: обе пары в `fixtures/ocr` (`aep_5.json`, -`aep_8_form4.json`) — ответы-ошибки ИС Сканирование («Не удалось определить тип документа.», пустой `table_structure`). -Эмулятор нашёл пару (в логе `scan-emulator`: `_aep_5.PDF -> …/Output//.json`; при -отсутствии пары сообщение было бы «…: нет эталонного ответа в фикстурах»). Поэтому успешный путь `image` -(`done`/`needs_check`, файл `results/…`) сквозной проверкой на текущих фикстурах не проходит — нужен успешный ответ ИС -в `fixtures/ocr`. Имя файла — `aep_5.PDF` (расширение в верхнем регистре; на macOS `aep_5.pdf` тоже находится, на Linux — нет). -`processing` виден ~5 с: задержка эмулятора 2 с плюс опрос горячей папки шлюзом. +Код `INVALID_DOCUMENT` здесь — **настоящий ответ ИС из фикстуры**: `aep_5.json` и `aep_8_form4.json` — ответы-ошибки +ИС Сканирование («Не удалось определить тип документа.», пустой `table_structure`); у `aep_3` и `aep_6` есть успешные +ответы (сценарий 2а). Эмулятор нашёл набор ответов (в логе `scan-emulator`: `_aep_5.PDF -> +/data/hotfolder/Output/`; при отсутствии набора сообщение было бы «…: нет эталонного ответа в фикстурах»). +Успешные ответы ИС есть (`aep_3.json` + `aep_3_ofr.json`, `aep_6.json`); шлюз склеивает все `*.json` каталога ответа и +отвечает `NOT_IMPLEMENTED` (нормализация — Срез 3), ошибочные файлы набора — в `metrics.warnings`. Имя файла — `aep_5.PDF` (расширение в верхнем регистре; на macOS `aep_5.pdf` тоже находится, на +Linux — нет). +`processing` виден ~10 с: задержка эмулятора 2 с, затем до `SCAN_POLL_SECONDS + SCAN_SETTLE_SECONDS` (5 + 2 с) после +первого опроса, увидевшего набор. + +**2а. `image` → успешный ответ ИС → `NOT_IMPLEMENTED`:** + +```bash +new_job image PDF ocr/aep_3.pdf && poll 60 +# 11:22:07 queued +# 11:22:08 processing +# 11:22:18 error NOT_IMPLEMENTED +dpsql -c "select status, error_code, metrics from dkb.recognition_job where id = '$JOB'" +# error | NOT_IMPLEMENTED | {"warnings": ["_ofr.json: INVALID_DOCUMENT: Не удалось определить тип документа."]} +new_job image PDF ocr/aep_6.pdf && poll 60 +# error NOT_IMPLEMENTED, metrics пусто +``` **3. Сервис недоступен → три повторные публикации → `dlq` / `NO_ACK`:** @@ -250,10 +264,13 @@ docker compose --profile services up -d --wait tabular-parser # вернут перезапускается (replay — вне Среза 0). Что сквозная проверка **не** покрывает (Срез 0): успешные результаты (`done`/`needs_check`, регистрация файла -`results/…` в `s3_object`) — заглушка парсера и фикстуры ИС дают только ошибки; `stored_file.status` остаётся +`results/…` в `s3_object`) — заглушка парсера и нормализатор шлюза Среза 0 (`NOT_IMPLEMENTED`) дают только ошибки, +хотя фикстуры ИС (`aep_3`, `aep_6`) успешные ответы содержат; `stored_file.status` остаётся `UPLOADED`, `current_recognition_job_id` не заполняется (маппинг результата — `NoopMapper`, Срез 2); у ошибок -`scan-gateway` `recognition_job.metrics` пустой (`tabular-parser` присылает `duration_ms`). Тестовые строки и объекты -остаются в БД и MinIO; полная очистка — `docker compose --profile services down -v`. +`scan-gateway` в `recognition_job.metrics` только `warnings` — по строке `<имя файла>: <код>: <сообщение>` на ошибочный +файл ответа ИС, если такие есть (`tabular-parser` присылает `duration_ms`). Тестовые строки и объекты остаются в БД и +MinIO; полная очистка — `docker compose --profile services down -v` (удаляет и общие тома `postgres-data`/`minio-data` +всех worktree: проект compose `arm-ka` общий). ## Переменные `.env` diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index a3d72c1..c98bc3b 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -181,7 +181,7 @@ services: # Эмулятор ИС Сканирование: тот же образ, что у шлюза (собирает сервис scan-gateway, см. arm-core-migrate); общий # том hotfolder с шлюзом. Переменные MinIO/NATS не нужны. - # Фикстуры ответов ИС — ../../fixtures/ocr (только чтение): пара <имя>.json для входного файла UUID_<имя>.ext. + # Фикстуры ответов ИС — ../../fixtures/ocr (только чтение): набор <имя>.json + <имя>_*.json для входного файла UUID_<имя>.ext. scan-emulator: profiles: ["services"] image: scan-gateway:dev