カスタム イベント トリガーを作成して処理する

Cloud Functions(第 2 世代)では、カスタム イベントに応じて関数をトリガーできます。これらのイベントは、Firebase SDK for Cloud Functions でネイティブにサポートされている Firebase イベントとは異なり、特別なイベント プロバイダまたは追加のイベント プロバイダによって提供されます。アプリは、カスタム イベント トリガーを介して、Firebase Extensions が提供するイベントに応答できます。また、独自のカスタム イベントを公開し、それに応じて関数をトリガーすることもできます。

すべてのカスタム イベントは、CloudEvents JSON イベント形式に準拠し、Eventarc に公開されます。Eventarc使用料が適用されます。

カスタム イベントで関数をトリガーする

カスタム イベントを公開(または Firebase Extensions からイベントを取得)し、それらのイベントに応じて関数をトリガーするには、次の基本的なフローを実装します。

  1. Eventarc チャネルで目的のイベントを公開するか、インストールした拡張機能により提供された利用可能なイベントを特定します。
  2. 関数コードでイベント ハンドラを使用して Eventarc チャネルのイベントをサブスクライブします。
  3. この関数で、CloudEvent オブジェクトで返されたペイロードを解析し、アプリが必要とするカスタム ロジックを実行します。

たとえば、ゲームアプリでは、ユーザーが上位 10 名の競技者のリーダーボードに入ったり、出たりしたときに、ユーザーに通知を送信できます。このアプリは、デフォルト チャネルにリーダーボード イベントを公開してから、ターゲット プッシュ通知をユーザーに送信する関数でイベントを処理します。

別の例として、アプリが大きな画像を処理できるように設計された拡張機能が、画像のサイズ変更の完了時にイベントを発生させるとします。この拡張機能がインストールされているアプリは、完了イベントの処理方法として、サイズ変更後の画像を指すよう、アプリ内のリンクを更新できます。

チャネルにイベントを公開する

Eventarc イベントはチャネルに公開されます。チャネルは、関連するイベントをグループ化し、アクセス権限を管理するための手段です。拡張機能をインストールする、またはカスタム イベントを使用する関数をデプロイすると、Firebase は us-central1 リージョンに firebase という名前のデフォルト チャネルを自動的に作成します。Firebase Admin SDK には、チャネルに公開するための eventarc サブパッケージが用意されています。

デフォルト チャネルを使用して信頼できるサーバー(または別の関数)からイベントを公開するには:

import {getEventarc} from 'firebase-admin/eventarc';

getEventarc().channel().publish({
    type: 'achieved-leaderboard',
    subject: 'Welcome to the top 10',
    data: {
      message: 'You have achieved the nth position in our leaderboard!  To see . . .'
    }
});

Firebase は、デフォルト チャネルを自動的に作成するだけでなく、イベントのソースを指定する環境変数 EVENTARC_CLOUD_EVENT_SOURCE を設定します。Cloud Functions for Firebase の外部でイベントを公開する場合は、イベント ペイロードに source フィールドを明示的に追加する必要があります。

カスタム イベントを処理する

拡張機能イベントを含むすべてのカスタム イベントは、onCustomEventPublished ハンドラまたは on_custom_event_published ハンドラで処理できます。まず、このハンドラを Firebase Admin SDK とともに Eventarc SDK からインポートします。

Node.js

const {onCustomEventPublished} = require("firebase-functions/v2/eventarc");
const logger = require("firebase-functions/logger");
const {initializeApp} = require("firebase-admin/app");
const {getFirestore} = require("firebase-admin/firestore");

Python

from firebase_admin import firestore, initialize_app
from firebase_functions import eventarc_fn

サンプル関数に示すように、関数のコードでイベント名を渡します。

Node.js

exports.onimageresized = onCustomEventPublished(
    "firebase.extensions.storage-resize-images.v1.complete",
    (event) => {
      logger.info("Received image resize completed event", event);
      // For example, write resized image details into Firestore.
      return getFirestore()
          .collection("images")
          .doc(event.subject.replace("/", "_")) // original file path
          .set(event.data); // resized images paths and sizes
    });

Python

@eventarc_fn.on_custom_event_published(
    event_type="firebase.extensions.storage-resize-images.v1.complete")
def onimageresized(event: eventarc_fn.CloudEvent) -> None:
    print("Received image resize completed event: ", event.type)

    if not isinstance(event.subject, str):
        print("No 'subject' data.")
        return

    # For example, write resized image details into Firestore.
    firestore_client: google.cloud.firestore.Client = firestore.client()
    collection = firestore_client.collection("images")
    doc = collection.document(event.subject.replace("/", "_"))  # original file path
    doc.set(event.data)  # resized images paths and sizes

特定の拡張機能ごとにイベント オブジェクトで返されるペイロードは、アプリケーション フローのカスタム ロジックの実行に使用できるデータを提供します。この場合、この関数は Admin SDK を使用して、サイズ変更された画像に関するメタデータを Cloud Firestore 内のコレクションにコピーし、イベントによって提供される subject からファイル名を取得して、イベントによって提供される data から取得したメタデータを保存します。

デフォルト以外のチャネルでイベントを公開、処理する

カスタム チャネルは、特別な権限または他の要件が必要な場合や、すべてのイベントに同程度の可視性とアクセス権を与えたくない場合に便利です。Google Cloud コンソールを使用して独自のチャネルを作成できます。イベントの公開とサブスクライブは、同じチャネルで行う必要があります。

デフォルト チャネル以外でカスタム イベントが公開される場合は、関数のコードでそのチャネルを指定する必要があります。たとえば、us-west1 ロケーションのデフォルト以外のチャネルで公開されるイベントを処理する場合は、そのチャネルを次のように指定する必要があります。

Node.js

import { onCustomEventPublished } from "firebase-functions/v2/eventarc";

export const func = onCustomEventPublished(
    {
      eventType: "firebase.extensions.storage-resize-images.v1.complete",
      channel: "locations/us-west1/channels/firebase",
      region: "us-west1",
    },
    (event) => { ... });

Python

@eventarc_fn.on_custom_event_published(
    event_type="firebase.extensions.storage-resize-images.v1.complete",
    channel="locations/us-west1/channels/firebase",
    region="us-west1")
def onimageresizedwest(event: eventarc_fn.CloudEvent) -> None:
    print("Received image resize completed event: ", event.type)
    # ...