9.5 KiB
ADDED Requirements
Requirement: Subject'ы NATS — настройки окружения
Subject'ы обмена SHALL задаваться секретами группы OPENBAO__NATS__ с одинаковыми ключами во всех трёх сервисах:
NATS_TABULAR_REQUEST_SUBJECT (по умолчанию files.tabular_uploaded), NATS_IMAGE_REQUEST_SUBJECT (по умолчанию
files.img_uploaded), NATS_RESULT_SUBJECT (по умолчанию files.tabular_parsed). У ядра и сервисов одного окружения
значения MUST совпадать. Каждый сервис SHALL при старте проверять все три имени: непустое, без пробельных символов, без
шаблонов * и >, без пустых токенов, три имени попарно различны; при нарушении сервис MUST NOT стартовать.
Учётные данные NATS (OPENBAO__NATS__NATS_JWT, OPENBAO__NATS__NATS_SEED) SHALL задаваться по окружению теми же
секретами, и их значения MUST NOT попадать в логи, repr настроек и тексты ошибок валидации конфигурации. Каждый
сервис SHALL писать используемые subject'ы в лог при старте и отдавать их в /healthcheck объектом subjects
(ключи tabular_request, image_request, result — только те, что использует сервис) независимо от состояния NATS.
Queue group'ы и schema_version от настроек subject'ов не зависят.
Scenario: Умолчания
- WHEN сервис стартует без ключей
OPENBAO__NATS__NATS_*_SUBJECT - THEN обмен идёт по
files.tabular_uploaded,files.img_uploaded,files.tabular_parsed
Scenario: Набор тестового окружения
- WHEN всем трём сервисам заданы одинаковые
OPENBAO__NATS__NATS_TABULAR_REQUEST_SUBJECT,NATS_IMAGE_REQUEST_SUBJECT,NATS_RESULT_SUBJECT,NATS_JWT,NATS_SEEDтестового окружения - THEN ядро публикует запросы и получает ack и результаты только по этим subject'ам; subject'ы по умолчанию не
используются,
recognition_job.request_subjectсодержит subject тестового окружения
Scenario: Недопустимый набор
- WHEN
NATS_RESULT_SUBJECTсовпадает с одним из subject'ов запроса, или имя содержит*,>или пробел - THEN сервис не стартует с ошибкой конфигурации, называющей ключ
Scenario: Разъехавшиеся настройки видны
- WHEN у ядра и сервиса заданы разные subject'ы ответа
- THEN
/healthcheck.subjects.resultядра и сервиса различаются; JWT и seed в ответе/healthcheckотсутствуют
Scenario: Ошибка конфигурации не раскрывает JWT
- WHEN сервис не стартует из-за ошибки валидации настроек при заданных
NATS_JWTиNATS_SEED - THEN текст ошибки и лог не содержат значений JWT и seed
MODIFIED Requirements
Requirement: Сообщение запроса распознавания
Тело сообщения на subject запроса tabular или image (настройки окружения NATS_TABULAR_REQUEST_SUBJECT /
NATS_IMAGE_REQUEST_SUBJECT, по умолчанию files.tabular_uploaded / files.img_uploaded) SHALL соответствовать
docs/contracts/recognition-request.schema.json v1.0: обязательные поля schema_version ("1.0"), job_id (uuid =
recognition_job.id), file_id (uuid = stored_file.id), pipeline (tabular | image), file_type
(XLS | XLSX | XLSB | PDF | PNG | JPG), original_name, s3 {bucket, key} исходника в роли uploads,
reply_deadline (date-time, UTC), attempt (≥ 1). Subject SHALL соответствовать pipeline.
Scenario: Публикация запроса ядром
- WHEN ядро переводит
recognition_jobизqueuedвpublished - THEN в subject, соответствующий
recognition_job.pipeline, публикуется сообщение, проходящее схему запроса, с заголовкомNats-Msg-Id=<job_id>:<attempt>
Scenario: Сообщение не по схеме
- WHEN сервис получает запрос, не проходящий схему (нет
s3.key, неизвестныйfile_type), но из тела извлекаются корректныеjob_idиfile_id - THEN сервис публикует результат со
status = error,error.code = SCHEMA_MISMATCHбез предшествующего ackprocessingи не падает;attemptдляNats-Msg-Idрезультата берётся из тела запроса, при его отсутствии реализации расходятся (tabular-parserберётattemptиз заголовкаNats-Msg-Idзапроса или не отвечает,scan-gatewayподставляет 1) — см. OQ-71
Scenario: Нечитаемый запрос
- WHEN сервис получает сообщение, из которого нельзя извлечь
job_id(не JSON, не объект,job_idотсутствует или не uuid), а значит нельзя собрать валидный конверт - THEN сервис ответа не публикует: запрос записывается в лог и отбрасывается; ядро не получит ack, повторит
публикацию
OUTBOX_MAX_REPUBLISHраз и переведёт задание вdlq(error_code = NO_ACK)
Scenario: Невалидный повтор запроса, уже находящегося в работе
- WHEN сервис получает запрос, не проходящий схему, но с
job_id, который уже в работе или обработан этим процессом - THEN конверт
SCHEMA_MISMATCHне публикуется (егоNats-Msg-Idresult:<job_id>:<attempt>совпал бы с настоящим результатом, и ядро отбросило бы настоящий как дубликат); запрос записывается в лог и отбрасывается
Scenario: Примеры контракта — иллюстрации
- WHEN запрос берётся из
docs/contracts/examples/request-*.json(вrequest-image.jsonreply_deadlineлежит в прошлом) - THEN он проходит схему: схема проверяет для
reply_deadlineлишь форматdate-time, но не сравнивает срок с текущим временем; пример — иллюстрация формы сообщения, а не готовое к исполнению задание; проверка срока — дело сервиса (scan-gatewayотвечаетerror TIMEOUT, еслиreply_deadlineистёк до отправки файла в ИС Сканирование)
Requirement: Сообщение результата распознавания
Тело сообщения на subject ответа (настройка окружения NATS_RESULT_SUBJECT, по умолчанию files.tabular_parsed)
SHALL соответствовать docs/contracts/recognition-result-message.schema.json
v1.0: обязательные поля schema_version ("1.0"), job_id, file_id, status (processing | done | needs_check |
error), service {name, version}; при status ∈ {done, needs_check} обязательны result_s3 {bucket, key} и
result_schema_version; при status = error обязателен error {code, message}; опциональны raw_s3_key
(только scan-gateway) и metrics. Поле group_schema в конверт NOT включается — источник recognition_job.group_schema
— файл результата.
Scenario: Успешный результат
- WHEN сервис завершил обработку файла
- THEN файл результата записан в S3 по ключу
results/{file_id}/{job_id}/result.json, а затем опубликован конверт соstatus = done | needs_check,result_s3указывает на этот файл, заголовокNats-Msg-Id=result:<job_id>:<attempt>
Scenario: Ошибка обработки
- WHEN сервис не смог обработать файл (нечитаем, таймаут внешней системы, тип не поддерживается)
- THEN публикуется конверт со
status = errorиerror.codeиз перечня схемы (UNSUPPORTED_FORMAT,UNREADABLE,TIMEOUT,SCHEMA_MISMATCH,NOT_IMPLEMENTED,FILE_READ_ERROR,INVALID_FORMAT,INVALID_DOCUMENT,RECOGNITION_FAILED,UNKNOWN_ERROR);result_s3может отсутствовать