Inquir Compute · пайплайны

Пайплайны по расписанию с историей, повторами и логами

Добавьте cron-триггер в пайплайн для повторяющейся работы: выражения проверяются при сохранении, история выполнения видна рядом с HTTP-вызовами, повторы настраиваются, а секреты и логи общие с API-функциями — без отдельного сервиса расписаний или crontab на VPS.

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

Суть ответа

Пайплайны по расписанию с историей, повторами и логами. Каждая задача по расписанию — пайплайн с cron-триггером. Платформа проверяет cron-выражение при сохранении, хранит время следующего запуска на пайплайн и создаёт запись вызова на каждое выполнение — всё доступно без SSH. Выбор лидера через advisory-lock в Postgres гарантирует, что каждое расписание срабатывает на одном узле, даже если рабочих узлов несколько.

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

  • Ночной ETL, ежечасная синхронизация, недельные отчёты, ротация сертификатов
  • Любая повторяющаяся задача, которой нужны видимая история прогонов и повторы

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

  • Когда состояние задач живёт на одном хосте, каждый деплой может сбросить расписание, каждая SSH-сессия — потенциальный выстрел в ногу, а каждая замена VPS — перечитывание двухлетнего runbook.
  • Секреты в файлах .env на сервере — кошмар для аудита; записи crontab не версионируются вместе с кодом приложения.

Тихие сбои традиционных задач по расписанию

  • Crontab на VPS: вывод уходит в почту root, которую никто не читает; повторов при сбое нет
  • systemd timers: надёжнее, но логи разбросаны, секреты вручную, истории нет
  • Kubernetes CronJob: правильные примитивы, но накладные расходы кластера для небольших команд

Задачи по расписанию падают тихо чаще любого другого примитива бэкенда. Задача крутится на VPS, скрипт выходит с ненулевым кодом, ошибка уходит в почтовый спул — и никто не знает, пока данные не устареют на три дня.

Почему crontab на сервере не переживает рост команды

Когда состояние задач живёт на одном хосте, каждый деплой может сбросить расписание, каждая SSH-сессия — потенциальный выстрел в ногу, а каждая замена VPS — перечитывание двухлетнего runbook.

Секреты в файлах .env на сервере — кошмар для аудита; записи crontab не версионируются вместе с кодом приложения.

Пайплайны по расписанию как полноценная часть платформы

Каждая задача по расписанию — пайплайн с cron-триггером. Платформа проверяет cron-выражение при сохранении, хранит время следующего запуска на пайплайн и создаёт запись вызова на каждое выполнение — всё доступно без SSH. Выбор лидера через advisory-lock в Postgres гарантирует, что каждое расписание срабатывает на одном узле, даже если рабочих узлов несколько.

Планировщик опрашивает каждые 30 секунд (минимальный интервал — 1 минута), поэтому срабатывание укладывается в ~30 с от запланированного времени. Задачи по расписанию делят секреты рабочего пространства и тот же стек наблюдаемости, что HTTP-маршруты: ночной ETL, недельные отчёты и ежечасная синхронизация видны в истории выполнения рядом с вызовами вебхуков и API.

crontab, systemd timers, Kubernetes CronJob и Inquir

Выбор планировщика зависит от зрелости эксплуатации и того, где уже живёт остальной стек. Таблица сравнивает четыре типичных подхода к повторяющейся бэкенд-работе — не edge-cron и не субсекундные тики.

crontab, systemd timers, Kubernetes CronJob и Inquir
Критерийcrontabsystemd timersKubernetes CronJobПайплайны Inquir по расписанию
Настройка и сопровождениеПравка crontab на хосте; выражение не проверяется при сохраненииUnit- и timer-файлы; надёжнее срабатывание, но упаковка всё ещё на уровне хостаYAML-манифесты и работающий кластер — даже для одной ночной задачиCron на триггере пайплайна; выражение проверяется при сохранении
История запусковПеренаправление stdout в файл или почту root — без структурированного аудитаjournalctl по unit; при росте числа задач — grep по сервисамЛоги подов и статус Job; хранение зависит от стека логирования кластераЗаписи вызовов рядом с HTTP-выполнениями — доступны без SSH
Повторы при сбоеНет — следующее срабатывание и есть единственный неявный повторOnFailure= может перезапустить unit; политики повторов на запуск в продуктовом UI нетbackoffLimit у Job; настраивается в манифесте, не рядом с историей APIЧисло повторов и задержка на каждом шаге пайплайна
Секреты.env на сервере или inline в shell — общие для всех задач на хостеEnvironmentFile в unit; ротация по-прежнему вручную на каждом хостеKubernetes Secrets — нативно для кластера, но отдельно от авторизации на шлюзе приложенияСекреты рабочего пространства, общие с HTTP-маршрутами — без параллельного .env на сервере
Изоляция между задачамиОдин UNIX-пользователь и окружение интерпретатора — конфликты зависимостей типичныМожно запускать от разных пользователей; всё равно одна машина, общее ядроПод на запуск — сильная изоляция, когда кластер уже оправданКонтейнер на вызов — та же модель изоляции, что у синхронных HTTP-обработчиков
Версионирование вместе с кодомСтроки crontab часто живут вне пайплайна деплояUnit-файлы могут лежать в git; расхождение между хостами всё равно случаетсяМанифесты в git/GitOps — отлично, когда K8s уже control planeБандлы функций и конфиг пайплайна версионируются вместе с деплоем платформы
Многошаговые процессыShell-скрипты с цепочкой команд — непрозрачные точки сбояОтдельные unit или bash в ExecStart — ручная оркестрацияОдин контейнер на CronJob; для DAG нужны Argo/Workflows или аналогиГрафы пайплайнов с рёбрами — extract, transform, load как узлы-функции
Перекрытие / долгие прогоныРучной flock или надежда — параллельные запуски портят общее состояниеНастройки concurrency на unit — логику всё равно пишете сами в обработчикеconcurrencyPolicy Forbid/Replace в спецификации CronJobЗащита skip-if-running и ключи идемпотентности в обработчике или в дизайне пайплайна
Когда уместноОдна VPS, один инженер, скрипты уже работают и редко падаютLinux-команды эксплуатации на systemd, готовые копать journalПродукт уже на Kubernetes с GitOps и логированием кластераПайплайны по расписанию и REST на одной платформе — история и повторы без YAML кластера

Возможности расписаний пайплайнов

Проверка cron-выражений

Выражения проверяются при сохранении пайплайна — некорректная запись падает сразу, а не тихо на следующем тике.

История прогонов и логи

Каждое выполнение по расписанию создаёт запись вызова: время старта, длительность, статус завершения, выходы шагов. Доступно без SSH.

Повторы и защита от наложения

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

Общие секреты

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

Как задать расписание пайплайна в Inquir

1

Написать обработчик задачи

Обычная функция. Секреты — из переменных окружения; на каждый шаг возвращайте структурированный выход.

2

Добавить расписание пайплайна

В визуальном редакторе пайплайнов соедините узел cronTrigger с узлом-функцией и введите cron-выражение. Сохраните пайплайн, чтобы проверить расписание.

3

Следить за историей прогонов

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

Ночная синхронизация с курсором

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

jobs/nightly-sync.mjs
export async function handler(event) {
  // event.trigger?.type === 'schedule' when fired by a cronTrigger node
  const since = process.env.SYNC_CURSOR ?? new Date(Date.now() - 86_400_000).toISOString();
  const records = await source.fetchUpdatedSince(since);
  if (records.length === 0) return { synced: 0, cursor: since };
  await destination.upsertBatch(records); // idempotent by record ID
  const newCursor = records.at(-1)?.updatedAt ?? since;
  // Store cursor for next run (update env var or external store)
  return { synced: records.length, cursor: newCursor };
}

Пайплайны по расписанию подходят для…

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

  • Ночной ETL, ежечасная синхронизация, недельные отчёты, ротация сертификатов
  • Любая повторяющаяся задача, которой нужны видимая история прогонов и повторы

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

  • Расписания чаще раза в минуту — минимальный интервал cron 1 минута; планировщик срабатывает в пределах ~30 с от запланированного времени, но точность до секунды не гарантирует

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

Может ли одна функция обслуживать HTTP и пайплайн по расписанию?

Да. Укажите тот же ID функции в узле-функции пайплайна и в HTTP-маршруте шлюза. Cron-триггер запускает пайплайн, который вызывает этот шаг.

В каком часовом поясе интерпретируются cron-выражения?

Для продакшен-расписаний используйте UTC, если требования не привязаны жёстко к рабочим часам по местному времени. Зафиксируйте допущение о часовом поясе в названии пайплайна.

Каков минимальный интервал cron?

Одна минута. Планировщик опрашивает каждые 30 секунд, поэтому реальное срабатывание может отстать от запланированной минуты до 30 секунд. Не рассчитывайте на интервалы короче 1 минуты и на точность до секунды.

Что если запуск длится дольше интервала?

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

Можно ли проверить задачу до следующего запуска по расписанию?

Да — вызовите функцию напрямую через шлюз или консоль. Это проверяет обработчик, а не расписание пайплайна или весь процесс.