LoginSignup
4
2

More than 3 years have passed since last update.

firebase functionsから別のfunctionsをキックする

Posted at

やりたいこと

  • functionsから別のfunctionsをキックしたい

先に代替案

firebase-queue というものがあるので、条件に合えばこれを使っても良さそう

  • firebase realtime databaseを利用している
  • 4年くらい更新されていないので怖い

ユースケース例

この記事では下記のような挙動を例にします

  • チャットアプリ
  • ユーザーAがメッセージを投稿する
  • 同じチャットルームに属するユーザーB, C, Dにpush通知が届く

具体的には下記のような処理フローになります

  • ユーザーAがメッセージを投稿するとfirestoreにドキュメントがinsertされる
  • ドキュメント作成のイベントを受けて、functionsAがキックされる
  • functionsAの中で
    • 同じルームのメンバー一覧を取得
    • メンバーそれぞれについて、push通知を発行するfunctionBをキックする

functionA

実装のイメージです

// ポイント1: functionsの中だけど、クライアント用のSDKを利用している
import firebaseClient from "firebase";

firebaseClient.initializeApp(client_sdk_config);
const functionsClient = firebaseClient
  .app()
  .functions("asia-northeast1");

// ポイント2: timeoutを指定することで、functionsBをキックするけど結果を待たない、ということができる
const functionB = functionsClient.httpsCallable(
  "functionB",
  { timeout: 1000 } // msec
);

const pushTargetUsers = ["user-B", "user-C", "user-D"];
const pushSendTasks = pushTargetUsers.map(async (userId) => {
  try {
    await functionB(userId);
  } catch (error) {
    if (e.code === "deadline-exceeded") {
      // functionBの完了は待たないので、timeoutエラーは無視する
      return;
    }

    throw e;
  }
});

await Promise.all(pushSendTasks);

ポイント

  • client用のSDKを使う
    • functions内部では普通はadmin SDKしか利用しない
    • しかしadmin SDKにはfunctionsを呼び出す機能がない
    • なのでclient用のSDKを利用することでfunctionsを呼び出す
  • functionsを呼び出すときにtimeout値を必要に応じてセットする

    • timeoutをセットしない場合
      • functionBが完了するまで待つことになる
      • この場合、functionBの返り値を受け取ることができる
      • 返り値を受け取りたい場合、わざわざ別functionに分離するメリットはあまりないので、このパターンはあまり利用機会がなさそう
    • timeoutをセットする場合
      • timeout以内にfunctionBが完了しなかった場合、 deadline-exceeded のエラーがスローされる
      • そのエラーは想定内なので握りつぶす
  • functionsのタイムアウトは2種類ある

↑xのタイムアウトを60秒、yのタイムアウトを10秒にセットしてfunctionを呼び出す、みたいなことができる

その場合、下記のような挙動になる

  • 10秒以内に処理が完了した場合
    • functionは正常にレスポンスを返す
  • 10秒以上かかった場合
    • 呼び出し側ではyのタイムアウトエラーがスローされる
    • しかし、キックされたfunction自体は10秒を超えても動いており、60秒以内に処理が完了すれば正常終了となる

感想

AWS LambdaではSDKが同期呼び出し、非同期呼び出しなどをサポートしており、もっとシンプルに同じことがやれます

firebase functionsでも同じことがやりたいと思って試行錯誤してこの結論に辿り着いたのですが、SDKでサポートしてくれるとありがたいですね...

また、そもそもfunctionからfunctionを直接呼び出すというのはあまり良い手段ではなく、AWSではstep functionsを使うべき場面だと思います

firebaseでも同様に別の手段を模索するべきなのかなとちょっと思いました

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2