Inquir Compute · фоновые задачи

Фоновые задачи с повторными попытками — без парка фоновых обработчиков

Фоновые задачи падают: API таймаутят, базы блокируются, сеть моргает. Платформе повторов нужны backoff на шаг, идемпотентные обработчики и история сбоев с поиском — а не цикл while в фоновом процессе. Пайплайны Inquir автоматически повторяют упавшие шаги, сохраняя завершённую работу в чекпоинтах.

Обновлено: 2026-10-11

Суть ответа

Фоновые задачи с повторными попытками — без парка фоновых обработчиков. Каждый шаг пайплайна повторяется при сбое независимо. Завершённые шаги остаются в чекпоинтах — перезапускается только упавший. Политика повторов (число попыток, backoff) — конфигурация, а не код приложения.

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

  • Async-работа из HTTP, вебхуков или cron, где сбои на следующих шагах ожидаемы
  • Многошаговые задачи, где перезапуск всей задачи при сбое дорог или небезопасен

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

  • Повтор всей задачи с нуля перезапускает завершённые шаги — двойные письма, двойные списания, дубли записей, если обработчики не идемпотентны.
  • Повторы с фиксированным интервалом добивают и без того падающие сервисы на следующем шаге. Экспоненциальному backoff нужны аккуратная настройка и jitter — шаблон, который большинство команд копирует с ошибками.

Почему повторы фоновых задач сложнее, чем кажется

Большинство команд начинают с fire-and-forget: поставили задачу и надеются на успех. Когда она падает, кто-то грепает логи и переигрывает вручную. В масштабе тихие сбои становятся утечкой выручки и злыми клиентами.

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

Где ломаются самодельные повторы

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

Повторы с фиксированным интервалом добивают и без того падающие сервисы на следующем шаге. Экспоненциальному backoff нужны аккуратная настройка и jitter — шаблон, который большинство команд копирует с ошибками.

Повторы шагов пайплайна как примитив платформы

Каждый шаг пайплайна повторяется при сбое независимо. Завершённые шаги остаются в чекпоинтах — перезапускается только упавший. Политика повторов (число попыток, backoff) — конфигурация, а не код приложения.

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

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

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

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

Паттерны повторов фоновых задач

Повторы на шаг с backoff

Упавшие шаги повторяются по настраиваемой политике. Завершённые не выполняются заново при падении следующего.

Идемпотентные обработчики задач

Проектируйте обработчики с расчётом на повторы: upsert по ID задачи, проверка перед записью, ключи дедупликации из payload триггера.

Триггер из любой точки входа

HTTP 202, подтверждение вебхука, cron-расписание или другая задача — все ставят работу в пайплайн с одной и той же семантикой повторов.

История сбоев с поиском

Ищите упавшие прогоны по времени, функции или тексту ошибки. Переигрывайте из сохранённого payload, не повторяя исходный HTTP-запрос.

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

Быстро принять, поставить надёжную задачу в очередь, а упавшие шаги повторит платформа.

1

Принять и поставить в очередь

HTTP-обработчик или вебхук сразу возвращает 202. Вызовите global.durable.startNew() с payload задачи.

2

Написать идемпотентные обработчики шагов

Каждый шаг пайплайна проверяет ключ дедупликации до побочных эффектов. Возвращайте структурированный выход для следующего шага.

3

Настроить политику повторов и оповещения

Задайте число попыток и backoff шага в конфигурации пайплайна. Оповещайте, когда доля сбоев превышает порог.

Фоновая задача с повторяемыми шагами пайплайна

HTTP-обработчик ставит работу в очередь одной строкой. Шаги пайплайна повторяются независимо при сбое на следующем шаге.

jobs/enqueue-export.mjs
export async function handler(event) {
  const { userId, format } = JSON.parse(event.body || '{}');
  if (!userId) return { statusCode: 400, body: JSON.stringify({ error: 'userId required' }) };
  const { instanceId: jobId } = await global.durable.startNew('export-data', undefined, { userId, format });
  return { statusCode: 202, body: JSON.stringify({ jobId, status: 'queued' }) };
}
jobs/export-step.mjs (шаг пайплайна — повтор при сбое)
export async function handler(event) {
  const { userId, format } = event.payload ?? {};
  const existing = await db.findExport(userId, event.instanceId);
  if (existing) return { statusCode: 200, body: JSON.stringify({ url: existing.url }) };
  const url = await generateAndUploadExport(userId, format);
  await db.saveExport(userId, event.instanceId, url);
  return { statusCode: 200, body: JSON.stringify({ url }) };
}

Кому подходят фоновые задачи с повторами

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

  • Async-работа из HTTP, вебхуков или cron, где сбои на следующих шагах ожидаемы
  • Многошаговые задачи, где перезапуск всей задачи при сбое дорог или небезопасен

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

  • Синхронная работа короче секунды без риска сбоя

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

Чем это отличается от повторов в BullMQ?

BullMQ повторяет задачи целиком в Redis через фоновый процесс. Inquir повторяет отдельные шаги пайплайна с чекпоинтами прогресса — без Redis и парка фоновых обработчиков.

Можно ли задать разную политику повторов на шаг?

Да. Число попыток и backoff настраиваются на каждый шаг пайплайна. Шаг с нестабильным внешним API можно повторять агрессивнее, чем локальную валидацию.

Что происходит после исчерпания повторов?

Прогон пайплайна помечается failed с полными логами. Дальше — ручной replay из истории выполнения или оповещение оператору.

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

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

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

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