diff --git a/context/03-architecture.md b/context/03-architecture.md index 9420f84..6a1bcb1 100644 --- a/context/03-architecture.md +++ b/context/03-architecture.md @@ -38,16 +38,19 @@ ## Контракт обмена через NATS (DECISION-4) -Схемы — `docs/contracts/` (v1.0): `recognition-request.schema.json` и `recognition-result-message.schema.json` — тела -сообщений, `recognition-result.schema.json` — файл результата в S3; примеры — `docs/contracts/examples/`. +Схемы — `docs/contracts/` (v1.0), JSON Schema 2020-12: [`recognition-request.schema.json`](../contracts/recognition-request.schema.json) +и [`recognition-result-message.schema.json`](../contracts/recognition-result-message.schema.json) — тела сообщений, +[`recognition-result.schema.json`](../contracts/recognition-result.schema.json) — файл результата в S3; примеры — +[`docs/contracts/examples/`](../contracts/examples/). Примеры проверяются схемами: `python scripts/validate_contracts.py` +(из корня репозитория docs). -| Поток | Subject | Кто пишет | Полезная нагрузка | `Nats-Msg-Id` | -|---|---|---|---|---| -| запрос | `recognition.tabular.request` / `recognition.image.request` | arm-core (outbox из `recognition_job`) | `schema_version`, `job_id`, `file_id`, `pipeline`, `file_type`, `original_name`, `s3 {bucket, key}` исходника, `reply_deadline`, `attempt` | `:` | -| результат | `recognition.result` | tabular-parser / scan-gateway | `schema_version`, `job_id`, `file_id`, `status` (done / needs_check / error), `error {code, message}`, `service {name, version}`, `result_s3 {bucket, key}`, `result_schema_version`, `raw_s3_key` (только scan-gateway), `metrics` | `result::` | +| Поток | Subject | Кто пишет | Полезная нагрузка | `Nats-Msg-Id` | Схема | +|---|---|---|---|---|---| +| запрос | `recognition.tabular.request` / `recognition.image.request` | arm-core (outbox из `recognition_job`) | `schema_version`, `job_id`, `file_id`, `pipeline`, `file_type`, `original_name`, `s3 {bucket, key}` исходника, `reply_deadline`, `attempt` | `:` | [request](../contracts/recognition-request.schema.json) | +| ack | `recognition.result` | tabular-parser / scan-gateway | конверт со `status = processing`, `job_id`, `file_id`, `service {name, version}` | `ack::` | [message](../contracts/recognition-result-message.schema.json) | +| результат | `recognition.result` | tabular-parser / scan-gateway | `schema_version`, `job_id`, `file_id`, `status` (done / needs_check / error), `service {name, version}`, `metrics`, `raw_s3_key` (только scan-gateway); при `done` / `needs_check` обязательны `result_s3 {bucket, key}` и `result_schema_version`, при `error` — `error {code, message}` | `result::` | [message](../contracts/recognition-result-message.schema.json); файл в S3 — [result](../contracts/recognition-result.schema.json) | `group_schema` в конверт не входит — ядро берёт его из `documents[].group_schema` файла результата при маппинге. -Конверт со `status = processing` — подтверждение взятия в работу (ack), `Nats-Msg-Id = ack::`. **На платформе NATS без JetStream** (ответ 03.10.2026): нет durable consumer'ов, серверного дедупа и redelivery. Поэтому гарантии доставки — на уровне приложения: сервисы подписаны queue group'ами (`tabular-parser`, `scan-gateway`), @@ -63,6 +66,11 @@ - Результат принимается подпиской queue group; `result_msg_id UNIQUE` = дедуп. Нет ack после повторов → `dlq`; потерянный результат → `reply_deadline` → `timeout`; replay = сброс в `queued` с `attempt + 1`. - Результат одного файла содержит **N документов**; ядро на каждый создаёт `document` и маппит данные. +- Три формы `Nats-Msg-Id`: запрос `:`, ack `ack::`, результат `result::`. + Ack (`processing`) сервис публикует **до чтения файла из S3**; повторная публикация запроса ядром идёт с тем же + `Nats-Msg-Id` и тем же `attempt`. Дубликат результата ядро определяет по `recognition_job.result_msg_id`. +- `schema_version` — `MAJOR.MINOR`; сервис отвергает запрос с неизвестным MAJOR результатом `error` с кодом `SCHEMA_MISMATCH` и подтверждает его + ack'ом, чтобы не зациклить доставку. - Сервисы не знают про БД и про бизнес-смысл: они возвращают структуру файла; нормализация счетов, резолв контрагентов, проверки — в ядре.