короткий запрос — понятный контракт

обработчик http должен проверить входные данные, права доступа и вернуть предсказуемый ответ. если действие занимает долгое время или зависит от нестабильного внешнего api, не заставляй вкладку ждать бесконечно. создай задачу, отправь её в очередь и верни идентификатор, по которому можно получить статус.

const job = await createJob(input);
await env.QUEUE.send({ id: job.id });
return Response.json(
  { id: job.id, status: "pending" },
  { status: 202 }
);

очередь не отменяет проверку прав

пользователь не должен уметь читать чужую задачу, просто подставив её номер. проверяй владельца на сервере при каждом обращении к статусу и результату. секреты провайдера остаются в окружении сервера, а не в javascript страницы и не в параметрах публичной ссылки.

повторы — обычная ситуация

пользователь может нажать дважды, сеть может оборваться после успешной записи, а очередь — доставить задачу повторно. для списания баланса, выдачи подписки и других важных действий нужен ключ идемпотентности и ограничение уникальности в базе. проверка «записи ещё нет» перед отдельной вставкой сама по себе не защищает от гонки.

тайм-аут и ошибка — часть api

ограничь ожидание внешнего сервиса и возвращай безопасное сообщение. не отправляй в браузер полный текст исключения с токенами и внутренними url. повторяй временные сбои с ограничением числа попыток; неверный пользовательский ввод повторять бессмысленно.

попробуй сам

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

есть вопрос или идея для следующего разбора?

написать
вернуться к заметкам