ベータ版Vercel Cron Jobsを試す
ここ最近で、Vercel Cronのベータ版がリリースされました。サーバレス関数の定期実行がとても楽になりますね。
今回はVercel Cronジョブの検証を行なっていきます。定期実行がわかりやすいよう、LINE Messageing APIを使用していきます(設定方法は割愛します)。
セットアップ
Next.jsプロジェクトからVercelデプロイまでを説明します。
Next.jsプロジェクト作成
まずは雛形をさくせいします。TypeScriptを使用します。
npx create-next-app vercel-cron-app
次にcronが起動したのがわかるよう、テスト用で作成したLINEチャネルで通知が来るか検証します。
api/cron.ts
import axios from 'axios'
import type { NextApiRequest, NextApiResponse } from 'next'
type Data = {
message: string
}
if (!process.env.LINE_API_TOKEN) {
throw new Error('トークンがありません')
}
if (!process.env.LINE_USER_ID) {
throw new Error('ユーザーIDがありません')
}
const lineClient = axios.create(
{
baseURL: 'https://api.line.me',
headers: {
Authorization: `Bearer ${process.env.LINE_API_TOKEN}`
}
}
)
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
await lineClient.post('v2/bot/message/push', {
to: process.env.LINE_USER_ID,
messages: [
{
type: 'text',
text: 'こんにちは。\ncronが起動しました。'
}
]
})
res.status(200).json({ message: 'DONE' })
}
cron設定ファイル
プロジェクトルート上に、cronを使用するためのvercel.json
を追加します。
schedule
ではUTCを考慮し、9時間時差で設定を行います。今回は日本時間で朝6時に起動するように設定します。
{
"crons": [
{
"path": "/api/cron",
"schedule": "0 21 * * *"
}
]
}
以下、Vercel公式から拝借したcron表現図になります。
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (0 is Sunday, 6 is Saturday)
# │ │ │ │ │
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
デプロイ
Vercelへデプロイします。
ここではVercel CLI
を使用していきます。
vercel deploy --prod
cron結果
動作していたのですが、なぜか50分ほどの差がありました。
原因はわかりません(分刻みの差まで考慮しないといけないわけじゃないよね?サーバーの負荷とかかな)。
ダイナミックルート
/api/post/[id].tsx
みたいな動的にパラメータを組み込むダイナミックルートにも対応している様子です。
セキュリティ面
誰でもcron関数が使用できたら良くないのでセキュリティはどうなっているのか気になります。
結論、現在組み込みでcronジョブを保護する方法はないそうです。その代わりにクエリ文字列を使用して関数とキーを共有する方法が書かれています。
vercel.json
{
"crons": [
{
"path": "/api/cron?secureKey=xxx",
"schedule": "0 21 * * *"
}
]
}
api/cron.ts
...
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
if (req.query.secureKey !== 'xxx') {
res.status(404).end()
return
}
...
}
Hobbyプランの制限
実は毎分設定しようとすると以下のようなエラー文が出ます。
これ、Hobbyプランだったら1日の使用に限りがあるっていう内容なんですね。10分毎にしようとしたら怒られました。
Hobby accounts are limited to daily cron jobs. This cron expression (*/10 * * * *) would run more than once per day. Upgrade to pro to unlock all Cron Jobs features on Vercel.
解消法はProプラン以上にしなければいけない様子です。
最後に
毎日1回使用したい場合にはHobbyプランでも問題なさそうです。検証結果で時間がズレた理由は分かりません、誰か教えていただけると幸いです。
1日の中で複数回しようしたければProプラン以上で進めるしかなさそうです。
プロジェクト仕様で、適材適所で使用できればと考えています。
Discussion