2026-10-13 12:06:11 +04:00

51 lines
2.0 KiB
Python

"""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>`).
"""
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}"