Решение владельца 08.10.2026: recognition.tabular.request → files.tabular_uploaded, recognition.image.request → files.img_uploaded, recognition.result → files.tabular_parsed (общий subject ack и результатов; files.img_parsed не используется). Тела сообщений, Nats-Msg-Id, queue group'ы и schema_version не меняются. Константы api/src/contract/subjects.py, докстринги, тесты, README, CLAUDE.md; копии схем api/contracts/ из docs/contracts/ побайтно; change nats-files-subjects с дельтой спеки. Сквозной change — RSHB/arm-ka-docs#74. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
4.1 KiB
MODIFIED Requirements
Requirement: Outbox публикует задания из queued
Фоновый публикатор SHALL с периодом OUTBOX_POLL_SECONDS (по умолчанию 5) выбирать задания status = queued
(с блокировкой FOR UPDATE SKIP LOCKED), формировать сообщение по recognition-request.schema.json v1.0 из
recognition_job ⋈ stored_file ⋈ s3_object и публиковать в subject по pipeline с заголовком
Nats-Msg-Id = <job_id>:<attempt>. После успешной публикации задание SHALL получить status = published,
published_at, request_msg_id, request_subject; при ошибке публикации задание SHALL остаться queued.
Scenario: Публикация запроса парсеру
- WHEN в
recognition_jobвставлена строкаqueuedсpipeline = tabular, связанная соstored_file(XLSX) и егоs3_object - THEN в течение 10 с в
files.tabular_uploadedпоявляется сообщение, проходящее схему запроса, сjob_id,file_id,s3.keyисходника,reply_deadline,attempt = 1, а строка переходит вpublishedс заполненнымrequest_msg_id
Scenario: NATS недоступен
- WHEN публикация завершается ошибкой соединения
- THEN задание остаётся
queued, ошибка залогирована, следующий цикл повторяет публикацию
Requirement: Ack сервиса переводит задание в processing
Получив в files.tabular_parsed конверт со status = processing для задания в published, ядро SHALL установить
status = processing, started_at, service_name, service_version и перевести файл задания в
stored_file.status = PROCESSING, если current_recognition_job_id файла равен этому заданию. Повторный ack для
задания в processing SHALL игнорироваться; ack для задания в другом статусе SHALL логироваться и не менять задание.
Scenario: Сервис подтвердил
- WHEN сервис опубликовал конверт
processingсjob_idопубликованного задания - THEN задание имеет
status = processing,started_atзаполнен,service_name = tabular-parser, файл —PROCESSING
Requirement: Соединение с NATS по шаблону, без JetStream
Ядро SHALL подключаться к NATS с nkeys-seed и JWT, если заданы OPENBAO__NATS__NATS_SEED/NATS_JWT, и без учётных данных,
если они пусты; подписываться на files.tabular_parsed в queue group arm-core; переподключаться автоматически.
Stream'ы и consumer'ы JetStream MUST NOT требоваться. Фоновые задачи SHALL запускаться при NATS_ENABLED=true.
Scenario: Dev-окружение compose
- WHEN ядро стартует с
DEBUG=true,NATS_ENABLED=trueи пустыми учётными данными против NATS без JetStream - THEN подписка активна,
/healthcheckотдаётnats = ok, в логах нет ошибок подключения
Scenario: Два инстанса ядра
- WHEN запущены два инстанса с
NATS_ENABLED=trueи опубликован один результат - THEN результат обработан ровно одним инстансом (queue group), строка задания изменена один раз
Scenario: NATS выключен
- WHEN
NATS_ENABLED=false - THEN приложение стартует, фоновые задачи не запускаются,
/healthcheckотвечает 200 сnats = off