しくじり日記

筋肉つけたい

Cloud Functions for Firebase でslackへの通知を定期実行する ~その1~

先日slackへの通知を定期実行する仕組みを作っていた際に、色々とハマったところを書いていきます。

はじめに

botや自動化、スクレイピングなどでスクリプトを24時間動かしたいと思う機会は多々あるのかと思います。 もちろん、サーバーを用意することでも実現できるのですが、最近ではよりハードルが低いサーバーレスの仕組みが多々用意されています。

その中で、自分が使用してみたのはCloud Functions for Firebaseです。 Firebaseの豊富な機能を簡単に使えるので、Databaseなどを利用してbotの機能を増やしていくこともできます。

セットアップ

firebase.google.com

まずはドキュメントに沿ってセットアップを進めていきます。

特筆することとして、今回自分は有料プラン(Blaze)を選んでいます。 理由としては、以下の二つが挙げられます。

1.有料プランでないとNode10以降のバージョンが使えない

後述するのですが、Nodeでslack用の環境を整えるのであれば、公式ドキュメントが豊富でサポートも手厚いBoltを使うのがおすすめです。ただ、このBoltはNode10以前のバージョンだと対応していない部分があるので、ほぼNode10以降を使える環境が必要になります。

slack.dev

参考までに、Cloud FunctionsのNodeのバージョンはpackage.jsonに記載されているので、この値を変更することでバージョンを更新することができます。

"engines": {
    "node": "10"
 }

2.他のプロダクトの管理が不要

定期実行を行う際に、内部的にはGoogle Cloud Pub/Sub と Cloud Scheduler APIが動いています。しかし、これら他のプロダクトの管理をしなくても、Cloud Functionsの書き方でスケジューリングをするだけで、簡単に定期実行ができるようになります。

実際、相当CPUやメモリを使ったり、かなりの回数関数を呼び出さない限りは無料枠の範疇で使えます。(参考: 月間呼び出し回数が200万回までは無料)

また、プロジェクト単位でプランを変えられるのは何となく意外に感じました。AWSGCPなど他のサービスがどうなってるのかを知らないので、どのレベルで違いがあるのかも知っていきたいですね。

定期実行の書き方

firebase.google.com

index.tsに以下のように記載すると、これだけで1日おきに定期的に処理を行ってくれます。

export const githubTrendSchedule = functions.pubsub
  .schedule("every 24 hours")
  .onRun((_) => {
    #GithubやSlack周りの処理
  });

他にCrontab の構文もサポートされているので、毎日〇〇時に処理を実行といった書き方もできます。

export const githubTrendSchedule = functions.pubsub
  .schedule("0 9 * * *")
  .timeZone("Asia/Tokyo")
  .onRun((_) => {
    githubTrendNotify();
  });

デプロイ

最後に、ここまで作った関数を実際にデプロイします。この時コンパイルが通らない時はもちろんですが、ESLintが通らない時もデプロイに失敗します。firebase init functions で生成されたeslintrc.js のルールが割と厳しいので、ある程度融通を聞かせるべきかは自分の良心と相談しましょう。

ハマりポイント

必要なパッケージをnpm i -save-devでインストールしてしまった場合、つまりpackage.jsondevDependencies に記載されていると、デプロイ先で上手く動かなくなります。 (こんなエラーが出ました)

i  functions: updating Node.js 10 function slack(us-central1)...
⚠  functions[slack(us-central1)]: Deployment error.
Function failed on loading user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs

推測なのですが、testやlint,コンパイル前のtypescriptのような開発環境用のdevDependenciesに記載されたパッケージは、デプロイ先の環境にはインストールされていないのかと思います。

まとめ

まずは定期的に処理を実行するところまでが完成しました。次はslackへの通知について書いていこうと思います。