Cron-завдання (Vercel)
Коротко: Маршрут, який Vercel сам автоматично викликає в задані моменти (замість того щоб його відвідував браузер чи користувач) — для повторюваних фонових завдань, які нікому не потрібно запускати вручну.
Докладніше: У Vercel cron-завдання оголошується у vercel.json (шлях + розклад у форматі cron, наприклад щодня о певній годині). Потім Vercel сам надсилає запит на цей маршрут — код за ним є цілком звичайним API-маршрутом, технічно не відмінним від того, який викликає людина.
Наш контекст: В Emzett /api/ticket-reminder використовує це для автоматичних листів-нагадувань, коли повідомлення адміністратора в тікетах підтримки лишаються без відповіді 12+ годин — він запускається щодня, і Michael сам про це не думає.
Подробиці
Оголошення та синтаксис cron
Оголошення у vercel.json відповідає стандартному синтаксису cron (хвилина, година, день, місяць, день тижня):
{
"crons": [
{ "path": "/api/ticket-reminder", "schedule": "0 12 * * *" },
{ "path": "/api/cart-cleanup", "schedule": "0 9 * * *" }
]
}"0 12 * * *" означає: щодня о 12:00 UTC. П’ять полів (зліва направо: хвилина 0-59, година 0-23, день місяця 1-31, місяць 1-12, день тижня 0-6) можна поєднувати з * (будь-яке значення), списками (1,15), діапазонами (1-5) і кроками (*/15 — кожні 15 хвилин) — той самий синтаксис, що й у класичного демона cron в Unix, який реалізація Vercel навмисно імітує, щоб наявні знання про cron переносилися напряму.
Автентифікація викликів cron
Важливий аспект безпеки: оскільки маршрут cron технічно є цілком звичайним, публічно доступним API-маршрутом, будь-хто інший у принципі міг би викликати його вручну — тому Vercel встановлює в справжніх викликах cron особливий заголовок Authorization (Bearer <CRON_SECRET>), який маршрут має перевіряти на боці сервера, щоб треті особи не могли вручну запускати той самий маршрут скільки завгодно разів (наприклад, щоб багаторазово розсилати листи-нагадування або створювати обчислювальний час/витрати):
export async function GET(request: Request) {
const authHeader = request.headers.get("authorization");
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response("Unauthorized", { status: 401 });
}
// власне логіка cron
}CRON_SECRET задається як звичайна змінна середовища й автоматично надсилається Vercel з кожним справжнім викликом cron.
Тайм-аути та обмеження виконання
Маршрути cron підпорядковуються тим самим обмеженням тайм-ауту функцій, що й інші serverless/edge-функції платформи — завдання, що триває довше за задану межу (наприклад, надсилання дуже багатьох листів у циклі), примусово переривається. Для довших пакетних завдань тому прийнято використовувати маршрут cron лише як «тригер», що запускає асинхронне фонове завдання (наприклад, через чергу), замість того щоб виконувати всю роботу синхронно всередині самого запиту cron.
Обмеження за тарифом
На безкоштовному тарифі Hobby частота запуску cron-завдань обмежена (наприклад, не більше одного разу на день на завдання) — для частіших інтервалів (щохвилини, щогодини) потрібен платний тариф. Крім того, більшість тарифів обмежують і максимальну кількість cron-завдань, які можна одночасно налаштувати на проєкт, що може стати актуальним для проєктів із багатьма повторюваними фоновими завданнями.
Див. також: Vercel, Змінні середовища