Сценарий

Serverless фоновые задачи на той же платформе, что и ваши API

Отвечайте браузерам и мобильным клиентам за миллисекунды, а асинхронные задачи запускайте через пайплайны — с ретраями, идемпотентными записями и трассами, как у синхронных вызовов.

Обновлено: 2026-06-28

Суть ответа

Serverless фоновые задачи на той же платформе, что и ваши API. Функции становятся шагами пайплайна; платформа отслеживает их выполнение так же, как синхронные вызовы, — фоновые задачи остаются доступными для поиска.

Когда подходит

  • Работа дольше нескольких секунд
  • Всплески нагрузки
  • Внешние API с непредсказуемой задержкой

На что обратить внимание

  • Каждый сервис, который изобретает свою consumer group в Redis, операционно отдаляется от того, как работают остальные ваши serverless-функции.
  • Без общей наблюдаемости фоновые задачи и пайплайны становятся чёрным ящиком рядом с REST-эндпоинтами.

Почему долгие HTTP-запросы ломают асинхронную работу

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

Шторм ретраев дублирует побочные эффекты, если не каждый обработчик фоновой задачи идемпотентен.

Почему самописные очереди прячут сбои

Каждый сервис, который изобретает свою consumer group в Redis, операционно отдаляется от того, как работают остальные ваши serverless-функции.

Без общей наблюдаемости фоновые задачи и пайплайны становятся чёрным ящиком рядом с REST-эндпоинтами.

Одна поверхность для HTTP, async-задач и пайплайнов

Функции становятся шагами пайплайна; платформа отслеживает их выполнение так же, как синхронные вызовы, — фоновые задачи остаются доступными для поиска.

Переиспользуйте секреты и сетевые решения и для онлайн-трафика, и для офлайн-пайплайнов.

Таймаут HTTP-запроса и таймаут фоновой задачи

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

Таймаут HTTP-запроса и таймаут фоновой задачи
КритерийТаймаут HTTP-запросаТаймаут фоновой задачи / шага пайплайна
Что ограничиваетОткрытое соединение клиент → шлюз → обработчик до отправки ответаВызов шага пайплайна или задачи из очереди после возврата HTTP-обработчика
Типичный потолокОт секунд до ~15 минут (например, Vercel 60–300 с, Lambda 900 с, Workers ~30 с CPU)Таймаут на шаг — дольше HTTP-лимитов; для многочасовой работы шаги объединяют в цепочку
Клиент ждёт?Да — сокет открыт, пока обработчик не завершится или не сработает таймаутНет — клиент получает 202 или ID задачи; работа продолжается асинхронно
РетраиПровайдер может повторить весь HTTP-запрос — риск дублирования побочных эффектовРетраи по шагам с идемпотентными обработчиками, независимо от ответа-подтверждения
НаблюдаемостьТолько логи запросов; оборванные прогоны видны как 504 или таймауты шлюзаИстория выполнения по шагам — с поиском, рядом с синхронными вызовами
Лучше подходит дляВалидация, авторизация, быстрые чтения, постановка в очередьЭкспорты, массовая синхронизация, ML-пайплайны, многоэтапный ETL
Паттерн InquirHTTP-обработчик валидирует, вызывает global.durable.startNew(), возвращает 202Шаг пайплайна выполняется с общими секретами и тем же каталогом функций

Паттерны фоновых задач, которые стоит стандартизировать

Веерная постановка

Одно событие — много задач с ясным владельцем.

Компенсация

Заложите откат или алерты на случай частичных сбоев.

Ограничение нагрузки

Регулируйте параллелизм, когда системы на следующем шаге хрупкие.

Как проектировать фоновые задачи на Inquir Compute

1

Описать payload

Версионируйте схемы, чтобы обновления не ломали уже идущие задачи.

2

Сделать идемпотентным

Защитите записи стабильными ключами.

3

Наблюдать

Настройте алерты на состояния вроде DLQ, если ваша инсталляция их показывает.

HTTP-таймаут → передача в асинхронную задачу

HTTP-обработчик сразу возвращает 202, не удерживая клиента. Обработчик задачи подхватывает работу с теми же секретами и наблюдаемостью, что и маршрут шлюза.

api/export.mjs (HTTP-обработчик)
export async function handler(event) {
  const { reportId, userId } = JSON.parse(event.body || '{}');
  if (!reportId) return { statusCode: 400, body: JSON.stringify({ error: 'reportId required' }) };
  // Enqueue the slow export job — returns immediately
  const { instanceId: jobId } = await global.durable.startNew('export-report', undefined, { reportId, userId });
  // Client polls GET /export-status/:jobId or receives a webhook when done
  return { statusCode: 202, body: JSON.stringify({ jobId }) };
}
jobs/export-report.mjs (шаг пайплайна)
export async function handler(event) {
  const { reportId, userId } = event.payload;
  // Idempotency key — safe to retry
  const existing = await db.exports.findByReportAndUser(reportId, userId);
  if (existing?.status === 'done') return { url: existing.url };
  const rows = await buildReport(reportId);
  const url = await storage.upload(rows, { key: `reports/${reportId}.csv` });
  await db.exports.upsert({ reportId, userId, url, status: 'done' });
  await notify(userId, { url });
  return { url };
}

Выбирайте async, когда…

Когда это уместно

  • Работа дольше нескольких секунд
  • Всплески нагрузки
  • Внешние API с непредсказуемой задержкой

Когда лучше выбрать другое

  • Действительно мгновенные чтения, которые спокойно укладываются в SLA

Частые вопросы

Реальна ли доставка «ровно один раз» для фоновых задач?

Ориентируйтесь на идемпотентные обработчики и ключи дедупликации; настоящее «ровно один раз» через сеть и хранилище встречается редко — проектируйте под «как минимум один раз» с безопасными повторами.

Когда HTTP должен отвечать 202 Accepted?

Когда пользовательская работа поставлена в очередь и вы можете указать ID задачи или выполнения — это лучше, чем держать сокет открытым до конца долгого экспорта.

Как пайплайны связаны с расписаниями и вебхуками?

Пайплайны стартуют по расписанию, HTTP, вручную или по событию. Обработчик вебхука может быстро ответить и поставить асинхронную задачу в очередь или запустить пайплайн — разные точки входа, тот же код оркестрации.