您的擴充功能可以包含Cloud Tasks 函數,這些函數會在擴充功能實例經歷以下任何生命週期事件時觸發:
- 擴充功能的實例已安裝
- 擴充的實例已更新為新版本
- 擴充實例的配置已更改
此功能最重要的用例之一是回填資料。例如,假設您正在建立一個擴充程序,用於產生上傳到 Cloud Storage 儲存桶的映像的縮圖預覽。擴充的主要工作將在onFinalize
Cloud Storage 事件觸發的函數中完成。但是,只有安裝擴充功能後上傳的映像才會被處理。透過在擴充功能中包含由onInstall
生命週期事件觸發的函數,您也可以在安裝擴充功能時產生任何現有影像的縮圖預覽。
生命週期事件觸發器的其他一些用例包括:
- 自動執行安裝後設定(建立資料庫記錄、索引等)
- 如果您必須發佈向後不相容的更改,請在更新時自動遷移數據
短期運行的生命週期事件處理程序
如果您的任務可以在最大 Cloud Functions 持續時間(使用第一代 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: {}
將您的函數註冊為一個或多個生命週期事件的處理程序:
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
擴充功能都使用生命週期事件處理程序來回填資料。