AiHummer доки
v1.0.x
RU EN

Доставка, outbox и восстановление

v1.0.x · обновлено 2026-06-26

Когда ход завершается, ответ ещё нужно доставить в канал, откуда он пришёл — надёжно и ровно один раз. AiHummer решает это транзакционным outbox, идемпотентными побочными эффектами и восстановлением хода после рестарта. Опциональная шина NATS может нести доставку в крупных развёртываниях.

Гарантированная доставка

Ответ не отправляется встроенно в конце хода. Вместо этого он ставится в очередь outbox в рамках той же работы, что его породила, а воркер доставки забирает его и отправляет в канал-источник. Поскольку ответ надёжно записан до того, как уйти, сбой между «ответ сформирован» и «ответ отправлен» не может его потерять — после рестарта запись outbox всё ещё на месте, и доставка продолжается.

ход формирует ответ
   └─▶ постановка в outbox (надёжно)
         └─▶ воркер доставки ─▶ канал-источник
               └─ подтверждено ─▶ помечено доставленным

Доставка идёт в паре с идемпотентностью, поэтому этот не-менее-однократный воркер даёт ровно-однократное внешнее поведение: resume-стабильный ключ реестра и барьер побочных эффектов гарантируют, что повторно доставленный или переигранный ответ отправится в канал лишь однажды (см. Мультиарендность и идемпотентность).

[!NOTE] «Ровно один раз» здесь описывает внешне видимый результат: пользователь получает ответ один раз. Внутри воркер может пытаться доставить более одного раза; слой идемпотентности сворачивает эти попытки в одну видимую отправку.

Восстановление хода после рестарта

Если gateway перезапускается посреди хода — деплой, сбой, перезагрузка хоста, — работа не бросается. Восстановление хода переигрывает прерванный ход, чтобы он завершился. Это безопасно только потому, что побочные эффекты идемпотентны: любая почта или отправка в канал, уже случившаяся до рестарта, распознаётся по своему ключу реестра и пропускается, а несостоявшиеся части доводятся до конца. Пользователь видит единый, полный ответ, а не наполовину готовый или дубль.

Опциональная шина NATS

По умолчанию доставка работает полностью через PostgreSQL, что сохраняет минимальное развёртывание в составе одного gateway плюс база. Для крупных или многошлюзовых конфигураций доставку можно вынести на шину NATS, настроив её URL:

# gateway.env
AIHUMMER_NATS_URL=nats://127.0.0.1:4222

Шина по-настоящему опциональна — оставьте AIHUMMER_NATS_URL незаданной, и outbox работает без неё. Когда она есть, NATS становится транспортом, по которому течёт работа доставки, что подходит горизонтально масштабируемым gateway за прокси.

[!TIP] Обновления без простоя запускают два и более gateway за обратным прокси. Планировщик остаётся единственным лидером через advisory-лок Postgres, а идемпотентная доставка означает, что дополнительные gateway могут делить нагрузку, ничего не отправляя дважды.

За чем следить

Доставка — это место, где проблемы надёжности проявляются первыми, поэтому именно её и нужно мониторить. AiHummer пушит телеметрию по OTLP (AIHUMMER_OTEL_ENDPOINT) и поставляет дашборды Grafana; эндпоинта Prometheus /metrics для скрейпа нет.

  • Диспозиции доставки (delivery dispositions) — исход каждой попытки доставки. Рост числа отказов указывает на проблему канала или нижележащего сервиса.
  • Глубина outbox — сколько ответов ждут доставки. Устойчивый рост означает, что доставка отстаёт.
  • Глубина DLQ — записи, исчерпавшие ретраи и попавшие в очередь недоставленных (dead-letter queue). Любой рост DLQ заслуживает разбирательства.

[!WARNING] Следите за этим вместе с задержкой хода и долей ошибок. Растущий outbox или DLQ — раннее предупреждение о деградации нижележащих каналов, даже когда сами ходы ещё проходят успешно.

Куда дальше