はじめに
CloudFunctionsで何らかの処理を実行して、その何分後かに別の処理を呼び出したいことがあります。
だけどsetTimeoutを使いたくない。事前にジョブを登録しておくわけにもいかない。
そんな時に以下の方法で実装してみました。
cloudSchedulerに対して、実行させたい日時(例:○分後)にジョブを登録。
実行時刻になると処理が呼び出される。
処理が終わったら不要になったジョブを削除。
サンプルコード
index.js
constfunctions=require('firebase-functions');constadmin=require('firebase-admin');const{google}=require('googleapis');constcloudScheduler=google.cloudscheduler('v1beta1');constmoment=require('moment');process.env.GOOGLE_APPLICATION_CREDENTIALS='path/to/serviceAccountKey.json';asyncfunctionauthorize(){constauth=newgoogle.auth.GoogleAuth({scopes:['https://www.googleapis.com/auth/cloud-platform'],});returnawaitauth.getClient();}constprojectId='my-project-id';constlocationId='us-central1';consttopicName='my-topic-name';constjobName='my-job-name';// 10分後処理実行を登録する処理exports.setTriggerIn10minutes=functions.https.onRequest(async(req,res)=>{// 現在時刻の10分後を取得し、cronフォーマットを生成constcronStr=moment().add(10,'minutes').format('m h D M *');// GCPのOAuth認証constauthClient=awaitauthorize();// ジョブ追加リクエストを作成constrequest={parent:`projects/${projectId}/locations/${locationId}`,resource:{name:`projects/${projectId}/locations/${locationId}/jobs/${jobName}`,schedule:cronStr,pubsubTarget:{topicName:`projects/${projectId}/topics/${topicName}`,data:Buffer.from(`${topicName}${cronStr}`).toString('base64'),},},auth:authClient,};// APIリクエストtry{constresponse=(awaitcloudScheduler.projects.locations.jobs.create(request)).data;console.log(JSON.stringify(response,null,2));}catch(err){console.error(err);}res.status(200).send('OK');});// 10分後に呼び出される処理exports.beCalledAfter10minutes=functions.pubsub.topic(topicName).onPublish(async(event,context)=>{constpubsubMessage=event.data;console.log(Buffer.from(pubsubMessage,'base64').toString());// TODO: 実際にやることを記述// GCPのOAuth認証constauthClient=awaitauthorize();// ジョブ削除リクエストを作成constrequest={name:`projects/${projectId}/locations/${locationId}/jobs/${jobName}`,auth:authClient,};// APIリクエストtry{awaitcloudScheduler.projects.locations.jobs.delete(request);}catch(err){console.error(err);}});
実行確認
最初の処理
ブラウザから以下のURLにアクセスし、Cloud Functionsを実行します。https://location-id-my-project-id.cloudfunctions.net/setTriggerIn10minutes
Cloud Functionsのログを確認し、setTriggerIn10minutesが正常に実行されたことを確認します。
Cloud Schedulerのジョブ一覧を確認し、トピック:my-topic-nameのジョブが10分後の実行予定で追加されたことを確認します。
10分後に呼び出される処理
Cloud Functionsのログを確認し、beCalledAfter10minutesが正常に実行されたことを確認します。
Cloud Schedulerのジョブ一覧を確認し、トピック:my-topic-nameのジョブが削除されたことを確認します。
注意事項
FirebaseのSparkプラン(無料)では使えませんでした。Blazeプラン(従量制)にする必要あり。
Cloud Schedulerの管理者権限をIAMで割り当てる必要あり。
実行時刻は秒単位での指定はできません。
といった制約があるので使える場面は少ないかもしれませんが、もしもの時に役立てばと思います。