拡張機能のインスタンスには、次のいずれかのライフサイクル イベントが発生した場合にトリガーされる Cloud Tasks の関数を含めることができます。
- 拡張機能のインスタンスがインストールされた
- 拡張機能のインスタンスが新しいバージョンに更新された
- 拡張機能インスタンスの構成が変更された
この機能の最も重要なユースケースの 1 つは、データのバックフィルです。たとえば、Cloud Storageバケットにアップロードされた画像のサムネイル プレビューを生成する拡張機能を作成しているとします。拡張機能の主な処理は、onFinalize
Cloud Storage イベントによってトリガーされる関数で行われます。ただし、拡張機能のインストール後にアップロードされた画像のみが対象になります。onInstall
ライフサイクル イベントによってトリガーされる関数を拡張機能に含めることで、拡張機能のインストール時に既存の画像のサムネイル プレビューを生成することもできます。
ライフサイクル イベント トリガーには他にも次のような用途があります。
- インストール後の設定の自動化(データベース レコードの作成、インデックス作成など)
- 下位互換性のない変更を公開する場合は、更新時にデータを自動的に移行します。
実行期間の短いライフサイクル イベント ハンドラ
タスクを Cloud Functions の最大継続時間(第 1 世代 API では 9 分)内に完了できる場合は、ライフサイクル イベント ハンドラをタスクキューの onDispatch
イベントでトリガーされる単一の関数として記述します。
export const myTaskFunction = functions.tasks.taskQueue()
.onDispatch(async () => {
// Complete your lifecycle event handling task.
// ...
// When processing is complete, report status to the user (see below).
});
次に、拡張機能の extension.yaml
ファイルで次の操作を行います。
taskQueueTrigger
プロパティを設定して、関数を拡張機能のリソースとして登録します。taskQueueTrigger
を空のマップ({}
)に設定した場合、拡張機能はデフォルト設定を使用して Cloud Tasks キューをプロビジョニングします。また、必要に応じてこれらの設定を調整することもできます。resources: - name: myTaskFunction type: firebaseextensions.v1beta.function description: >- Describe the task performed when the function is triggered by a lifecycle event properties: location: ${LOCATION} taskQueueTrigger: {}
関数を 1 つ以上のライフサイクル イベントのハンドラとして登録します。
resources: - ... lifecycleEvents: onInstall: function: myTaskFunction processingMessage: Resizing your existing images onUpdate: function: myOtherTaskFunction processingMessage: Setting up your extension onConfigure: function: myOtherTaskFunction processingMessage: Setting up your extension
関数は、
onInstall
、onUpdate
、onConfigure
の任意のイベントに登録できます。これらのイベントはすべて省略可能です。推奨: 拡張機能が機能するために処理タスクが必要ない場合は、ユーザーが構成したパラメータを追加し、ユーザーが有効にするかどうかを選択できるようにします。
たとえば、次のようなパラメータを追加します。
params: - param: DO_BACKFILL label: Backfill existing images description: > Should existing, unresized images in the Storage bucket be resized as well? type: select options: - label: Yes value: true - label: No value: false
関数でパラメータが
false
に設定されている場合、早期に終了します。export const myTaskFunction = functions.tasks.taskQueue() .onDispatch(async () => { if (!process.env.DO_BACKFILL) { await runtime.setProcessingState( "PROCESSING_COMPLETE", "Existing images were not resized." ); return; } // Complete your lifecycle event handling task. // ... });
長時間実行タスクの実行
Cloud Functions の最大継続時間内にタスクを完了できない場合は、Admin SDK の TaskQueue.enqueue()
メソッドを使用してジョブをキューに登録し、タスクをサブタスクに分割して、各サブタスクを順番に実行します。
たとえば、Cloud Firestore データをバックフィルするとします。クエリカーソルを使用して、ドキュメント コレクションをチャンクに分割できます。チャンクを処理した後、次のように開始オフセットを進めて、別の関数呼び出しをキューに追加します。
import { getFirestore } from "firebase-admin/firestore";
import { getFunctions } from "firebase-admin/functions";
exports.backfilldata = functions.tasks.taskQueue().onDispatch(async (data) => {
// When a lifecycle event triggers this function, it doesn't pass any data,
// so an undefined offset indicates we're on our first invocation and should
// start at offset 0. On subsequent invocations, we'll pass an explicit
// offset.
const offset = data["offset"] ?? 0;
// Get a batch of documents, beginning at the offset.
const snapshot = await getFirestore()
.collection(process.env.COLLECTION_PATH)
.startAt(offset)
.limit(DOCS_PER_BACKFILL)
.get();
// Process each document in the batch.
const processed = await Promise.allSettled(
snapshot.docs.map(async (documentSnapshot) => {
// Perform the processing.
})
);
// If we processed a full batch, there are probably more documents to
// process, so enqueue another invocation of this function, specifying
// the offset to start with.
//
// If we processed less than a full batch, we're done.
if (processed.length == DOCS_PER_BACKFILL) {
const queue = getFunctions().taskQueue(
"backfilldata",
process.env.EXT_INSTANCE_ID
);
await queue.enqueue({
offset: offset + DOCS_PER_BACKFILL,
});
} else {
// Processing is complete. Report status to the user (see below).
}
});
前のセクションの説明に従って、extension.yaml
に関数を追加します。
ステータスの報告
すべての処理関数が正常に完了するか、エラーが発生した場合、Admin SDK の拡張機能ランタイム メソッドを使用して、タスクのステータスを報告します。このステータスは、Firebase コンソールの拡張機能の詳細ページで確認できます。
正常な完了と致命的でないエラー
正常な完了と致命的でないエラー(拡張機能が非機能状態にならないエラー)を報告するには、Admin SDK の setProcessingState()
拡張機能ランタイム メソッドを使用します。
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setProcessingState(processingState, message);
以下の状態を設定できます。
致命的でない状態 | |
---|---|
PROCESSING_COMPLETE |
タスクが正常に完了したことを報告する場合に使用します。例: getExtensions().runtime().setProcessingState( "PROCESSING_COMPLETE", `Backfill complete. Successfully processed ${numSuccess} documents.` ); |
PROCESSING_WARNING |
部分的な成功を報告する場合に使用します。例: getExtensions().runtime().setProcessingState( "PROCESSING_WARNING", `Backfill complete. ${numSuccess} documents processed successfully.` + ` ${numFailed} documents failed to process. ${listOfErrors}.` + ` ${instructionsToFixTheProblem}` ); |
PROCESSING_FAILED |
タスクは実行できないものの、拡張機能が使用不能にならないエラーを報告する場合に使用します。例: getExtensions().runtime().setProcessingState( "PROCESSING_FAILED", `Backfill failed. ${errorMsg} ${optionalInstructionsToFixTheProblem}.` ); 拡張機能が使用不能になるエラーを報告するには、 |
NONE |
タスクのステータスをクリアするために使用します。必要に応じて、この値を使用してコンソールからステータス メッセージを消去できます(たとえば、 getExtensions().runtime().setProcessingState("NONE"); |
致命的なエラー
拡張機能の動作を妨げるエラー(必要な設定タスクの失敗など)が発生した場合は、setFatalError()
を含む致命的なエラーを報告します。
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setFatalError(`Post-installation setup failed. ${errorMessage}`);
タスクキューの調整
taskQueueTrigger
プロパティを {}
に設定すると、拡張機能インスタンスのインストール時に、デフォルト設定の Cloud Tasks キューがプロビジョニングされます。また、特定の値を指定することで、タスクキューの同時実行の上限と再試行の動作を調整できます。
resources:
- name: myTaskFunction
type: firebaseextensions.v1beta.function
description: >-
Perform a task when triggered by a lifecycle event
properties:
location: ${LOCATION}
taskQueueTrigger:
rateLimits:
maxConcurrentDispatches: 1000
maxDispatchesPerSecond: 500
retryConfig:
maxAttempts: 100 # Warning: setting this too low can prevent the function from running
minBackoffSeconds: 0.1
maxBackoffSeconds: 3600
maxDoublings: 16
lifecycleEvents:
onInstall:
function: myTaskFunction
processingMessage: Resizing your existing images
onUpdate:
function: myTaskFunction
processingMessage: Setting up your extension
onConfigure:
function: myOtherTaskFunction
processingMessage: Setting up your extension
これらのパラメータの詳細については、Google Cloud ドキュメントの Cloud Tasks キューの構成をご覧ください。
タスクキューのパラメータを taskQueue()
に渡して指定しないでください。これらの設定は無視され、extension.yaml
の構成と構成のデフォルトが優先されます。
たとえば、次の場合は機能しません。
export const myBrokenTaskFunction = functions.tasks
// DON'T DO THIS IN AN EXTENSION! THESE SETTINGS ARE IGNORED.
.taskQueue({
retryConfig: {
maxAttempts: 5,
minBackoffSeconds: 60,
},
rateLimits: {
maxConcurrentDispatches: 1000,
maxDispatchesPerSecond: 10,
},
})
.onDispatch(
// ...
);
拡張機能のタスクキューを構成する唯一の方法は、extension.yaml
の taskQueueTrigger
プロパティを使用することです。
例
公式の storage-resize-images
、firestore-bigquery-export
、firestore-translate-text
拡張機能はすべてライフサイクル イベント ハンドラを使用して、データをバックフィルします。