Andrey Epifancev f794ebabcb NATS: subject'ы и JWT из OPENBAO__NATS__*, SecretStr, скрытие входа в ошибках (#31)
- NATSSettings: subject'ы запроса и ответа из окружения (имена контракта по умолчанию), проверка формата и попарного
  различия; NATS_SEED и NATS_JWT — SecretStr; request_subjects() для request_subject(pipeline, subjects).
- hide_input_in_errors во всех классах настроек: ошибка «нет поля» не печатает вход группы с JWT и seed.
- build_nats_auth читает секреты через get_secret_value().
- Схемы контракта скопированы из docs/contracts (request, result-message).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:38:50 +04:00

55 lines
2.4 KiB
Python
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.

"""Subject'ы NATS, заголовок дедупликации и идентификаторы сообщений контракта v1.0.
Источник: `docs/context/03-architecture.md`, «Контракт обмена через NATS»; схема recognition-request
(`Nats-Msg-Id = <job_id>:<attempt>`) и recognition-result-message
(`ack:<job_id>:<attempt>` / `result:<job_id>:<attempt>`).
Модуль намеренно совпадает с копией в arm-core. `request_subject`, `REQUEST_SUBJECTS`, `IMAGE_REQUEST_SUBJECT` и
значение `"image"` в `Pipeline` tabular-parser не использует (он слушает только `tabular`) — это сознательный паритет
с arm-core, а не мёртвый код.
"""
import uuid
from collections.abc import Mapping
from typing import Literal, get_args
Pipeline = Literal["tabular", "image"]
NATS_MSG_ID_HEADER = "Nats-Msg-Id"
RESULT_SUBJECT = "files.tabular_parsed"
TABULAR_REQUEST_SUBJECT = "files.tabular_uploaded"
IMAGE_REQUEST_SUBJECT = "files.img_uploaded"
REQUEST_SUBJECTS: Mapping[str, str] = {
"tabular": TABULAR_REQUEST_SUBJECT,
"image": IMAGE_REQUEST_SUBJECT,
}
def request_subject(pipeline: str, subjects: Mapping[str, str] = REQUEST_SUBJECTS) -> str:
"""Subject запроса по pipeline. `subjects` — карта `pipeline → subject` окружения
(`NATSSettings.request_subjects()`); по умолчанию — имена контракта: `tabular` → `files.tabular_uploaded`,
`image` → `files.img_uploaded`."""
try:
return subjects[pipeline]
except KeyError:
raise ValueError(f"неизвестный pipeline {pipeline!r}: допустимы {', '.join(get_args(Pipeline))}") from None
def request_msg_id(job_id: uuid.UUID | str, attempt: int) -> str:
"""`Nats-Msg-Id` запроса: `<job_id>:<attempt>`."""
return f"{job_id}:{attempt}"
def ack_msg_id(job_id: uuid.UUID | str, attempt: int) -> str:
"""`Nats-Msg-Id` ack (`status = processing`) на `files.tabular_parsed`: `ack:<job_id>:<attempt>`."""
return f"ack:{job_id}:{attempt}"
def result_msg_id(job_id: uuid.UUID | str, attempt: int) -> str:
"""`Nats-Msg-Id` результата (`done | needs_check | error`) на `files.tabular_parsed`.
Форма: `result:<job_id>:<attempt>`.
"""
return f"result:{job_id}:{attempt}"