きっかけ
大学の研究で進化計算というものを行っており、進化の処理を行うために利用しました。
本記事では、firebaseプロジェクトの作成、functionsの設定まで済んでいるというところをスタート地点として説明していきます。
自動でタスクを実行する流れ
今回は、firestoreにドキュメントが作成されたら、その情報を元にスケジュールを作成するサンプルを作成します。
流れとしては、
- 定期的に実行したいfunctions.pubsubを作成
- スケジュールの作成、削除
- functions.onCreateでスケジュールの作成、削除を発火
pub/subを利用する理由として、httpsだと誰からでも起動できてしまうため、セキュリティ的なデメリットがあるからです。
また、スケジューラと紐付ける時に相性がいいです。
では、順を追って説明していきます。
pubsubの作成
今回のサンプルではスケジューラで送られてきたメッセージをログに表示していきます。
const locationId = "asia-northeast1"; // region
const projectId = "scheduler-api-sample"; // firebaseのプロジェクト名
const topicName = "sample-pubsub"; // pub/subの名前
const jobName = "sample-job"; // スケジューラのジョブの名前
...
exports.samplePubSub = functions.pubsub
.region(locationId)
.pubsub.topic(topicName)
.onPublish(message => {
const messageBody = message.data ? message.data : null
console.log("messageBody:", message.data)
})
...
スケジュールの作成、削除
モジュールの追加
yarn add @google-cloud/scheduler
でモジュールを追加します。
注意点として、プロジェクト/package.json
でなくプロジェクト/functions/package.json
に対して追加してください。
初期化
const scheduler = require("@google-cloud/scheduler");
const client = new scheduler.v1beta1.CloudSchedulerClient({ projectId });
projectIdを渡して、どのプロジェクトに対してジョブを追加するか予め設定しておきます。
ジョブの作成
const formattedParent = client.locationPath(projectId, locationId);
const formattedJobName = client.jobPath(projectId, locationId, termDocId);
const registerJob = () => {
const interval = `0 0 * * *`; // crontab or App Engine Cron
const req = {
parent: formattedParent,
job: {
name: formattedJobName,
schedule: interval,
pubsubTarget: {
topicName: `projects/${projectId}/topics/${topicName}`,
data: Buffer.from('published').toString("base64")
}
}
};
client
.createJob(req)
.then(res => console.log(res[0]))
.catch(e => console.error(e));
}
formattedParent
=> projects/[PROJECT_ID]/locations/[LOCATION_ID]
formattedJobName
=> projects/[PROJECT_ID]/locations/[LOCATION_ID]/jobs/[JOB_ID]
を生成してくれます。
パラメータについては公式サイトに詳しく載っていますので、もっと知りたい方は以下のリンクを参考にしてください。
登録済みのジョブのリストや更新などについても載っています。
ジョブの削除
const unRegisterJob = () => {
const req = {
name: formattedJobName
};
client.deleteJob(req).catch(e => console.error(e));
};
こちらはジョブの名前を指定するだけで削除ができます。
functionsで追加する
exports.sampleFirestoreOnCreate = functions
.region(locationId)
.firestore
.document("samples/{docId}")
.onCreate((snap, context) => {
registerJob();
}
これでsamples
コレクションにドキュメントが作成されたらジョブが設定されるようになりました!
0 0 * * *
間隔に設定しているので、毎日0時0分になったらpublishTarget.data
で渡したメッセージ(published
)をログで出力します。
いろいろ試していて、ジョブの名前が重複していると登録ができなかったので、自動で追加する場合にはfirestoreで自動生成されるドキュメントIDなどを使うといいかもです。
僕はdocId
をregisterJob
に渡してjobId
として登録することで重複を避けました。
所感
schedulerのAPI利用については記事があまり無いのでこのモジュールにたどり着くまで結構時間がかかりました。もっとGCPを使いこなしたいですね。
みなさんよいfirebaseライフを!
※ 間違いや動かないぞ!ということがありましたらコメントにお願いします。