RussiaAPI

Практическое руководство для разработчиков

DLQ для webhook video API: как не потерять callback после повторов

DLQ для webhook video API нужна не для того, чтобы бесконечно повторять ошибку, а чтобы не потерять событие после ограниченного числа осмысленных попыток. Видео-задача может завершиться, а ваш callback-handler временно не сможет записать статус: база недоступна, схема изменилась, очередь переполнена или downstream-сервис отвечает 5xx. Если просто вернуть ошибку до исчерпания повторов поставщика, состояние останется неизвестным. Отдельная dead-letter queue сохраняет безопасную запись, даёт оператору контекст и позволяет повторить обработку без создания нового видео.

Граница сервиса. RussiaAPI — независимый сторонний API gateway, а не официальный сервис OpenAI, Anthropic, Google или производителя модели. OpenAI-совместимый формат описывает контракт отдельных запросов, но не обещает одинаковые модели, цены, хранение данных, webhook или права ключей. Используйте только собственный RUSSIAAPI_API_KEY на сервере; не передавайте внешние ключи, cookie, пароли, коды подтверждения или лишние персональные данные.

Где DLQ находится в цепочке видео-задачи

Сначала отделите получение callback от бизнес-обработки. Webhook-handler проверяет подпись, дедуплицирует delivery ID и помещает компактное событие в устойчивую основную очередь. Worker читает событие, сверяет внутреннюю операцию, обновляет статус и запускает разрешённые последующие действия. Если обработка временно неудачна, событие получает ограниченную следующую попытку с задержкой. После установленного числа попыток оно переходит в DLQ вместе с причиной, временем и безопасным внутренним ID.

Не кладите в DLQ bearer-токен, webhook secret, полный raw body, пользовательский prompt, приватную ссылку на файл или чужой ключ. Для расследования обычно достаточно delivery ID, task ID, внутреннего operation ID, типа события, счётчика попыток, короткого класса ошибки и времени. Если нужен исходный payload, храните его отдельно, зашифрованно, с минимальным сроком и ограниченным доступом — но сначала убедитесь, что он действительно нужен для вашей политики и требований.

Сделайте retry ограниченным и различайте причины

Повтор полезен для временных сбоев: короткий сетевой timeout, 429 с понятным backoff или временный 5xx. Невалидный статус, отсутствующая внутренняя операция, ошибка подписи или несовместимость схемы обычно не станут правильными от десяти одинаковых повторов. Классифицируйте результат worker: retryable, terminal или manual_review. Для retry используйте ограниченное число попыток, экспоненциальную задержку с небольшим jitter и общий deadline, чтобы очередь не захватывала ресурсы бесконечно.

Не складывайте retry поставщика, HTTP-клиента, очереди и базы в одну неявную волну. Один callback может прийти повторно извне, а ваш worker ещё раз получит его из очереди. Дедупликация и идемпотентное обновление статуса нужны на каждом durable-переходе. Базовый принцип создания одной видео-задачи описан в материале об idempotency key; DLQ продолжает его для уже созданных задач.

Сохраняйте запись для безопасного replay

Replay не означает «нажать повторить всё». Оператор сначала видит policy: событие прошло проверку подписи, какая операция затронута, почему упал worker, сколько было попыток и не завершилась ли задача уже другим путём. Затем система берёт сохранённый безопасный event reference, ставит его в новую попытку и сохраняет автора решения. Новая попытка использует тот же delivery ID и не вызывает повторную генерацию видео. Если задача уже имеет конечный корректный статус, replay становится no-op с записью причины.

Ниже упрощённый пример на Node.js 18+ показывает классификацию и перевод в DLQ в памяти. Он запускается как отдельный модуль, но память не переживает рестарт, поэтому это только схема алгоритма. В production используйте вашу БД или брокер с транзакционной/уникальной записью, политикой доступа и мониторингом. Поле taskId не является правом на скачивание: выдача результата всегда остаётся в авторизованном маршруте приложения.

const mainQueue = [];
const deadLetterQueue = [];
const MAX_ATTEMPTS = 3;

function classify(error) {
  return error?.retryable === true ? 'retryable' : 'terminal';
}

export async function processVideoEvent(event, updateOperation) {
  try {
    await updateOperation(event.operationId, event.taskId, event.status); // Должно быть идемпотентно по deliveryId.
    return { state: 'done', deliveryId: event.deliveryId };
  } catch (error) {
    const attempts = (event.attempts || 0) + 1;
    const reason = classify(error);
    const safeEvent = { deliveryId: event.deliveryId, operationId: event.operationId, taskId: event.taskId, status: event.status, attempts, reason };
    if (reason === 'retryable' && attempts < MAX_ATTEMPTS) {
      mainQueue.push(safeEvent); // В production: enqueue с задержкой и транзакцией.
      return { state: 'retry_scheduled', deliveryId: event.deliveryId };
    }
    deadLetterQueue.push(safeEvent); // В production: доступ по ролям, аудит replay.
    return { state: 'dead_lettered', deliveryId: event.deliveryId };
  }
}

Решение, где разместить DLQ, зависит от вашей инфраструктуры. Важно не название технологии, а свойства: событие не теряется до подтверждения, повтор ограничен, причина наблюдаема, а replay не обходит tenant-права и не создаёт новую дорогостоящую операцию.

Добавьте сверку состояния как безопасный fallback

Webhook — быстрый сигнал, но не единственный источник истины. Для операций, которые долго находятся в промежуточном статусе, можно запускать ограниченную server-side сверку с текущим разрешённым API-методом или внутренним реестром. Не превращайте это в агрессивный polling: задайте допустимый интервал, бюджет и срок, после которого задача получает честный статус «требует проверки». Сверка особенно полезна, если callback попал в DLQ или поставщик исчерпал свои повторы.

Сверка не должна подменять договорённый webhook-контракт и не позволяет обходить лимиты. Она сравнивает только операцию, на которую у вашего backend уже есть право, и обновляет статус через те же правила переходов. Для выбора между обычным polling и callback используйте руководство по polling или webhook; для аутентичности callback — проверку подписи.

Метрики и операционный чек-лист

Наблюдайте глубину DLQ, возраст старейшего события, долю terminal-ошибок, число replay, задержку до конечного статуса и расхождение между callback и сверкой. Резкий рост DLQ — сигнал проверить релиз handler, схему, секрет callback, доступ базы или rate limit, а не причина автоматически многократно отправлять исходный запрос. Настройте короткий runbook: кто имеет право открыть запись, кто утверждает replay, когда нужна ротация секрета и как уведомить владельца tenant.

  1. Webhook после проверки быстро попадает в устойчивую очередь с delivery ID.
  2. Worker отличает временную ошибку от terminal-причины и имеет ограниченный retry.
  3. DLQ хранит только безопасный контекст и не содержит ключей, prompt или приватных URL.
  4. Replay использует ту же операцию и идемпотентные переходы, не создавая новое видео.
  5. Для зависших задач есть ограниченная сверка статуса и понятный операционный runbook.

DLQ повышает наблюдаемость, но не гарантирует доставку или доступность модели. Сообщайте пользователю фактический статус и соблюдайте применимые требования, лимиты и условия сервиса.

Проверьте сценарий в RussiaAPI

Создайте собственный тестовый ключ в консоли, проверьте текущий каталог моделей и контракт callback, затем выполните минимальный server-side тест на синтетических данных. Расширяйте доступ и нагрузку только после измеримой проверки.

Открыть консоль RussiaAPI

FAQ

Когда событие надо отправить в DLQ?

После ограниченных осмысленных попыток либо сразу при terminal-причине, которую повтор не исправит. Событие должно сохранить безопасный ID и причину, чтобы его можно было проверить без раскрытия секретов.

Можно ли replay из DLQ создать повторное видео?

Не должно. Replay повторяет обработку уже принятого callback с тем же delivery ID и внутренней операцией. Создание новой video-задачи — отдельный путь с отдельной идемпотентностью и правами.

Заменяет ли DLQ polling?

Нет. DLQ сохраняет неуспешные события для расследования и replay. Ограниченная сверка статуса может быть fallback для зависших операций, если она разрешена вашим текущим контрактом и имеет бюджет.

Читайте также