Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Cloud Functionsで作るSlack App
Search
mikan3rd
September 29, 2021
Programming
930
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
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
220
GitHubハンズオン講座 — 実務レベルのチーム開発のフローを身につけよう
junhat6
0
110
Androidだけじゃない、DroidKaigiで広がった私の技術スタック
akkeylab
0
100
Java 27新機能 / Java 27 new features
kishida
2
180
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.6k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
340
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
2.6k
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
18
19k
半永久的に提供し続けられるプライベートクラウドを目指して ― 利用者の認知負荷を抑えるAPI抽象化とハードウェア世代交代の基盤設計
tomokon
0
270
カツオ、ご期待ください
suneo3476
0
120
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
980
AHC070解法紹介
eijirou
0
140
Featured
See All Featured
We Are The Robots
honzajavorek
0
380
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
530
Ethics towards AI in product and experience design
skipperchong
2
400
Docker and Python
trallard
47
4.2k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
510
Rebuilding a faster, lazier Slack
samanthasiow
85
9.7k
How to train your dragon (web standard)
notwaldorf
97
6.8k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.7k
How to build a perfect <img>
jonoalderson
1
6k
Test your architecture with Archunit
thirion
2
2.4k
Building AI with AI
inesmontani
PRO
1
1.3k
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