Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Cloud Functionsで作るSlack App
Search
mikan3rd
September 29, 2021
Programming
920
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Cloud Functionsで作るSlack App
mikan3rd
September 29, 2021
More Decks by mikan3rd
See All by mikan3rd
どうしてフロントエンドにReact/TypeScriptが必要なのか?〜そしてサーバーサイドへ〜
mikan3rd
1
1.2k
Other Decks in Programming
See All in Programming
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
14
2.9k
dRuby over BLE
makicamel
2
410
なぜ型を書くのか? TSKaigi2026で改めて考える #tskaigi_smarthr
kajitack
0
210
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
210
20260623_Loop Engineeringで自分の分身の問い合わせBotを作る
ryugen04
0
170
act1-costs.pdf
sumedhbala
0
170
TAKTでAI駆動開発の品質を設計する
j5ik2o
7
1.7k
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1k
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
270
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
140
Vite+ Unified Toolchain for the Web
naokihaba
0
700
フィードバックで育てるAI開発
kotaminato
1
110
Featured
See All Featured
BBQ
matthewcrist
89
10k
Practical Orchestrator
shlominoach
191
11k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
The Cult of Friendly URLs
andyhume
79
6.9k
Making the Leap to Tech Lead
cromwellryan
135
10k
Docker and Python
trallard
47
3.9k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.4k
Building Applications with DynamoDB
mza
96
7.1k
What does AI have to do with Human Rights?
axbom
PRO
1
2.2k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
640
Un-Boring Meetings
codingconduct
0
330
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
340
Transcript
Cloud Functionsで作る Slackアプリ 2021/09/29 mikan3rd
Who is mikan3rd? • Hiroki Ota ◦ 基本 mikan3rd という名前で活動してます
• 1992年生まれ、エンジニア5年目 ◦ JavaScript / TypeScript / Ruby / Python / Go ◦ TypeScript / React が特に得意 • 現在は株式会社ZENKIGEN所属 ◦ 採用向けweb面接「harutaka」 ◦ 録画面接のAI分析「harutaka エントリーファインダー」 ◦ ライブ面接のAIサポート「harutaka インタビューアセスメント」 ◦ エンジニア職も募集中!! • Google CloudのProfessional Cloud Developer認定 ◦ 弊社のインフラは GCPがメインです Twitter: @mikan_the_third
本題 Cloud Functionsで作る Slackアプリ
Q. こんなこと思ったことありませんか? • HTTPリクエストで呼び出せる処理を作りたい! • PubSubで非同期に実行させたい! • cronみたいに定期実行させたい! • (JavaScriptでいう)オブジェクトをそのまま
DBに保存したい! • CI経由で自動デプロイさせたい! • 1ヶ月あたり無料枠〜数十円におさまる範囲で動かしたい!
それ、 で Serverlessでできます!!
Firebaseとは? • mBaaS(mobile Backend as a Servie) • GCPのサービスのうちアプリ開発によく使う機能をまとめて使いやすくしたやつ ◦
データベースFirestore ◦ ストレージは Cloud Storage for Firebase ◦ ユーザー認証は Authentication ◦ サーバーレスコンピューティングは Cloud Function ◦ などなど(モバイルアプリ向けの機械学習もある) • インフラや一部バックエンドは GCPに任せてサーバーレスで開発できる! ◦ 上記の機能をフロントから使える
Cloud Functions for Firebaseの良いところ • 関数単位のちょっとした複数の処理をサーバーレスで用意できる ◦ フレームワーク不要、関数だけでバックエンドサーバーができる ◦ サーバー(の管理が)レス
• 様々なトリガーで関数を起動できる ◦ HTTPリクエスト ◦ PubSub ◦ Cloud Schedulerの自動PubSub連携(定期処理) ◦ フロント側からSDK経由で直接呼び出し ◦ Firestore / Storage にデータの変更があった場合 ◦ などなど • firebase-toolsを使用したデプロイが楽 ◦ `firebase deploy` だけ! ◦ Firestoreのセキュリティルールとかもまとめてデプロイ可能 • エミュレーターを使えばローカルでも動作確認可能
Firestoreのいいところ • 何も準備がいらないので楽 ◦ テーブルを追加する必要なし(ドキュメント追加と共に自動で作成される) • ちょっとしたクエリなら使える ◦ RedisなどのKey-Value型のDBではクエリが書けないが、 Firestoreはドキュメント型なので簡単なク
エリなら書ける • 少量の使用なら無料枠におさまる ◦ Cloud SQLなどマネージドDBは最低スペックでも 1ヶ月数千円かかる ◦ Google Compute EngineにMySQLサーバーを自前で立てることもできるが面倒
今回作ったやつ
Lively • LivelyはSlack上のコミュニケーションをより便利に楽しくするための機能を複数備えたアプリで す! • https://github.com/mikan3rd/lively • 様々なチャンネルから人気の投稿を探して通知します • 週間・月間で人気のあった投稿を振り返ります
• アプリのホームタブから簡単に設定ができます • 新しく作成された絵文字やチャンネルをお知らせします • privateチャンネルには関与しないようになっているため安心です
Livelyの構成 • TypeScript (Node.js) • Firebase ◦ Cloud Functions ◦
Firestore • Slack App ◦ OAuth Permission ◦ App Home ◦ Interactive Components ◦ Event Subscription
Slack App
Slack App とは? • Slack AppをSlackにメッセージを投げたり、Slackのデータを取得したり、SlackのUIを使って操 作したりできる • 無料!!
OAuth認証 • アプリを作成したworkspace以外でも使え るようにするためには、OAuth認証で他の workspaceの認証トークンを取得する必要 がある ◦ Slack Appを作成したworkspaceのみで使 用する場合は不要
• 使用したいAPIに応じてscopeを付与する必 要がある ◦ 今回のアプリでは privateチャンネルに対 するアクセス権はない • 認証用URLにリダイレクトするendpointと認 証処理用のendpointを用意
Interactive Component & App Home • Interactive ComponentとはSlackのメッセージにテキス トだけでなくボタンやセレクトボックスなどを表示できる 機能
◦ 各パーツはJSON形式で決まった構造で組み立てる必要が ある ◦ https://app.slack.com/block-kit-builder でプレビューでき る • App HomeをONにするとSlack上でアプリを選択した時 にHomeタブが表示できるようになる ◦ ここにもInteractive Componentを表示させることができる ◦ 今回の場合はここでアプリの設定ができるようにしている • Interactive Componentで選択された結果を受け取る endpointが必要
Event Subscription • 特定のイベントが発生した時にリクエストを送ってくれる webhook的なやつ ◦ 先ほどのApp Homeが開かれた時には `app_home_opened` というイベントが送られてくるので最新
のデータを反映した Interactive Componentを送っている ◦ `channel_created` `emoji_changed` のイベントが送られた 時にチャンネル作成の通知やスタンプ追加の通知をリアル タイムで送るようにしている(簡単) • イベントを受け取るための endpointが必要
実際に触ってみて分かった注意事項
• 外部へのアクセスなど一部の機能には従量課金プランに切り替えが必要 ◦ と言っても従量課金プランにも無料枠はあるのでそんなに気にすることはない • コールドスタート ◦ 実行環境はゼロから初期化されるため、関数の実行までその分の時間がかかる • タイムアウト
◦ 最大9分 ◦ そもそも呼び出し回数、メモリ、実行時間による従量課金なので長く重い処理には向かない • デプロイによる課金 ◦ `firebase deploy` は内部的に Cloud Build を使用しているため Cloud Buildの実行時間が課金対象となる(無料枠あるので そう超えないはず) ◦ 関数は無料枠のない Container Registry に保存されるため、その分のストレージ料金がかかる ◦ デプロイする度に古い Containerが削除されずに溜まっていって課金対象となってしまう • 使えるのは Node.js (JavaScript / TypeScript)だけ ◦ 普通のCloud FunctionはRuby / Python / Java / PHP / Go でも使えます ◦ https://firebase.google.com/docs/functions/functions-and-firebase ◦ `gcloud functions deploy` Cloud Functions for Firebaseを使う際の注意
Firestoreを使う際の注意 • 読み取り、書き込み、削除のドキュメントの数による従量課金 ◦ 頻繁に上記の処理が発生する場合や大量のデータを扱う場合は不向き ◦ ページングなどでドキュメントの合計数が欲しい場合もデータの読み取りとして課金される ◦ コンソール上で上記の処理を行った場合も課金対象 •
NoSQLなのでRDBでいうリレーションを再現し辛い ◦ 一応、サブコレクションや参照型など用意されているがクセがある • NoSQLなのでカラムごとに型を制限できない ◦ KeyとValueのように格納できるが型の制限はできないので想定外の値が入ってもエラーにならない ◦ またマイグレーションのような概念もない • 複数Keyを使ったクエリを書くには別途 indexを貼る必要がある
Slackアプリを使う際の注意 • レート制限 ◦ 同じAPIを呼べるのは1分間に20回までなどの制限がある ◦ OAuth認証であればトークンごとに回数が測定される • メッセージを指定して取得する APIが存在しない
◦ そもそもメッセージにサロゲートキーがない(ちなみにメッセージへのリンク取得 APIではチャンネル IDをタイムスタンプを指定して取得するのでこれが複合キーっぽい) ◦ 例えば1年前のとあるメッセージのチャンネル IDとタイムスタンプが特定できていても、 API経由で取 得するには1年前まで順番に遡るしかない ◦ メッセージを順番に取得する際にも件数を指定しないといけないので、ヤマカンででかい件数を指定 して繰り返す処理をしないといけない(レート制限にかからないように) • Event APIには3秒以内にレスポンスを返さないとリトライが走る ◦ 何か処理を行う時間がないので非同期にしないといけない ◦ リクエストヘッダーの `x-slack-retry-num` `x-slack-retry-reason` を見ればハンドリング可能
スタンプの多いメッセージを取得・通知するには? • 一定数以上のスタンプがついたメッセージを取得したいが、そのような APIはない ◦ メッセージの一覧を取得する APIで全件取得してスタンプ数でフィルタリングする処理を行っている ◦ ただしメッセージの一覧はチャンネルごとにしか取得できないので、チャンネル数だけメッセージの全 件取得を行わなかればいけない
◦ チャンネル数が多い場合はレート制限に引っかかってしまうため調整している ▪ Cloud Task ◦ 上記の処理を毎時実行する定期処理にしている ◦ また、一度通知したメッセージが重複して通知されないように、通知済みのメッセージのチャンネル ID とタイムスタンプは Firestoreに保存してチェックしている • 週間、月間で集計するには? ◦ 毎時の処理で取得したスタンプの多いメッセージを保存して流用したい ◦ しかし、メッセージを指定して取得できる APIがないため、上記の処理の取得期間を週間と月間に伸 ばして実行するチカラ技の処理となってしまっている・・・・
スタンプ数の多いスレッドも通知したい! • メッセージ一覧取得時にスレッドのデータは付与されない • スレッドの一覧はメッセージ指定でしか取得できない • つまり全てのメッセージに対してスレッド一覧取得を行うしかない ◦ 流石にやめた
伝えたいこと • ちょっとした用途のバックエンドにはCloud Functions for Firebase / Firestoreが便利!安い! • Slackアプリは簡単に作れる(けど制約があるので思い通りにな
らないことも) • 今回登場してないけどCloud Runも便利!
ご静聴 ありがとうございました! Qiitaでより詳しいコードの解説してます https://qiita.com/mikan3rd/items/b3f333314c15c866ab84