Логотип Аурабаза
аурабазадокументы
документы›Edge Functions›Jobs, cron and the DLQ

Задания, cron и очередь недоставленных писем

Как запустить работу вне запроса: что такое задание, как оно повторяется, как cron создает задания и что делать с заданиями, которые в конечном итоге не работают.

9 мин читать·Уровень средний·Пересмотрено 12 окт. 2026 г.
Этот текст на английском языке был создан автоматически на основе французского оригинала и еще не проверялся.
Эта страница была переведена автоматически. Английская версия является авторитетной.
#
очередь

1. Поставьте задание в очередь

Задание — это один фоновый вызов функции. Поставьте его в очередь с сервера с ключом service_role.

server/enqueue.tstypescript
import { createClient } from '@aurabase/aurabase-js'

const admin = createClient(process.env.AURA_URL!, process.env.AURA_SERVICE_ROLE_KEY!)

const { data: job, error } = await admin.functions.enqueueJob('send-report', {
  payload: { month: '2026-10' },
  delaySecs: 60,   // подождите 60 секунд перед первой попыткой
  maxAttempts: 3,  // по умолчанию
})
ВариантПо умолчаниюЗначение
payloadnullJSON передается функции в качестве тела запроса.
delaySecs0Секунды ожидания перед первой попыткой. До этого момента задание останется pending.
maxAttempts3Общее количество попыток, включая первую

Вы читаете задание обратно с помощью getJob(id) или listJobs({ status, limit }) (limit находится в диапазоне от 1 до 500, по умолчанию 50). Задание имеет status, attempts, max_attempts, error и даты scheduled_at, started_at, completed_at.

Вакансии — это серверный инструмент

enqueueJob, getJob и listJobs нужен ключ service_role. Открытый ключ получает 403.

#
Обработчик

2. Что получает ваша функция

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

ЧастьЦенить
МетодJOB (не POST)
Путь/jobs/<job id>
ТелоЗадание payload в формате JSON
Заголовки удостоверенийНет: x-aura-role и x-aura-user-id отсутствуют.
aurabase/functions/send-report/index.tstypescript
Deno.serve(async (req) => {
  const jobId = new URL(req.url).pathname.split('/').pop()
  const { month } = await req.json()
  // …собрать и отправить отчет, используя jobId в качестве ключа идемпотентности
  return new Response('ok')
})

Реальный вызов зарегистрирован {"method":"JOB","path":"/jobs/d443d541-…","role":null,"userId":null,"body":"{\"items\":[\"a\",\"b\"],\"order\":42}"}.

Задание выполняется без пользователя: не полагайтесь на x-aura-user-id. Если работа принадлежит пользователю, поместите идентификатор пользователя в полезные данные.

#
Повторные попытки

3. Жизненный цикл и повторные попытки

statusestext
pending ──claimed──▶ running ──▶ completed
   ▲                    │
   └── after 5 s ◀── failed (attempts left)
                        └──▶ dead (no attempts left)
  • Задание запускает хотя бы один раз. Она может запуститься дважды, если рабочий процесс остановится во время ее работы, поэтому сделайте функцию идемпотентной.
  • Неудачная попытка повторяется через фиксированную задержку в 5 секунд, пока не будет достигнута maxAttempts. Тогда задание будет dead. Задержка и количество попыток по умолчанию являются настройками службы (JOB_RETRY_DELAY_SECS, JOB_MAX_RETRIES).
  • Задание, которое по-прежнему имеет статус running после аренды (по умолчанию 450 секунд), восстанавливается службой.
  • По умолчанию завершенные задания хранятся 14 дней.
Ошибка HTTP в вашей функции не является сбоем

Задание называется completed, как только ваша функция отвечает на, независимо от кода состояния. В реальном запуске функция, возвращающая 500, создала задание completed после одной попытки и никогда не повторялась.

Задание завершается сбоем и повторяется только в случае сбоя самого вызова: функция не существует или неактивна, среда выполнения недоступна или время вызова истекло. Если вы хотите повторить попытку, когда ваш собственный код обнаружит ошибку, поставьте в очередь новое задание из обработчика (с delaySecs для отката) вместо того, чтобы полагаться на код состояния.

В том же реальном запуске задание для несуществующей функции прошло через следующую последовательность: попытка 1 завершилась неудачно через 3 секунды с Fonction 'ghost' introuvable, попытка 2 завершилась неудачно примерно через 9 секунд, и задание стало dead с attempts равным max_attempts.

#
Восстановление

4. Очередь недоставленных писем

Мертвые задания остаются в очереди, их можно просмотреть и повторить. У этих маршрутов пока нет метода SDK: используйте HTTP с ключом service_role.

terminalbash
# список мертвых вакансий
curl "$AURA_URL/v1/functions/jobs/dlq" -H "apikey: $AURA_SERVICE_ROLE_KEY"

# повторить одно задание
curl -X POST "$AURA_URL/v1/functions/jobs/$JOB_ID/retry" -H "apikey: $AURA_SERVICE_ROLE_KEY"

# повторить каждое мертвое задание (до 1000)
curl -X POST "$AURA_URL/v1/functions/jobs/dlq/requeue" -H "apikey: $AURA_SERVICE_ROLE_KEY"
# → {"данные":{"requeued":1},"meta":null}

При повторной попытке задание возвращается в pending без сброса счетчика попыток, поэтому оно получает ровно одну дополнительную попытку и возвращается в dead, если снова происходит неудача. Устраните причину (например, разверните отсутствующую функцию), прежде чем повторять попытку.

#
Расписание

5. Расписание с помощью cron

Запись cron не вызывает саму функцию: каждый раз, когда она запускается, она ставит задание в очередь.

server/cron.tstypescript
await admin.functions.createCronJob('nightly-cleanup', '0 3 * * *', 'cleanup', {
  payload: { dryRun: false },
})

const { data: crons } = await admin.functions.listCronJobs()
await admin.functions.deleteCronJob('nightly-cleanup') // по ИМЯ, а не по идентификатору
  • Расписание имеет 5 полей (min hour day month weekday) или 6 полей (sec min hour day month weekday). В расписании из 5 полей впереди 0 секунд: */1 * * * * сохраняется как 0 */1 * * * *.
  • Псевдонимы, такие как @daily, отклоняются с помощью 400, указывающего ожидаемый формат.
  • Время указано в формате UTC.
  • last_run и next_run являются null до первого запуска. В реальном запуске расписание, созданное в 15:40, сработало в 15:41:00, а затем показало next_run 15:42:00.
  • Полезная нагрузка замораживается при создании записи.
  • Удаление неизвестного имени возвращает 404. Удаление записи cron также останавливает ее запуск.
  • В SDK нет getCronJob или updateCronJob: удалите запись и создайте ее заново.

Для работы исключительно с базой данных расширение Postgres pg_cron позволяет избежать обратного пути к функции: см. страницу Cron.

Последнее обновление · 12 окт. 2026 г.