افزونه شما میتواند شامل توابع Cloud Tasks باشد که وقتی یک نمونه افزونه هر یک از رویدادهای چرخه عمر زیر را طی میکند، فعال میشوند:
- یک نمونه از افزونه نصب شده است
- یک نمونه از افزونه به نسخه جدید بهروزرسانی میشود
- پیکربندی یک نمونه افزونه تغییر کرده است
یکی از مهمترین موارد استفاده از این ویژگی، پر کردن مجدد دادهها است. برای مثال، فرض کنید در حال ساخت افزونهای هستید که پیشنمایشهای کوچک از تصاویر آپلود شده در یک مخزن Cloud Storage ایجاد میکند. کار اصلی افزونه شما در تابعی که توسط رویداد onFinalize Cloud Storage فعال میشود، انجام میشود. با این حال، فقط تصاویری که پس از نصب افزونه آپلود میشوند، پردازش میشوند. با گنجاندن تابعی که توسط رویداد onInstall lifecycle فعال میشود، میتوانید هنگام نصب افزونه، پیشنمایشهای کوچک از هر تصویر موجود نیز ایجاد کنید.
برخی دیگر از موارد استفاده از محرکهای رویداد چرخه عمر عبارتند از:
- خودکارسازی تنظیمات پس از نصب (ایجاد رکوردهای پایگاه داده، فهرستبندی و غیره)
- اگر مجبورید تغییرات ناسازگار با نسخههای قبلی را منتشر کنید، دادهها را به طور خودکار در هنگام بهروزرسانی منتقل کنید
گردانندههای رویداد چرخه عمر کوتاهمدت
اگر وظیفه شما میتواند به طور کامل در حداکثر مدت زمان Cloud Functions (9 دقیقه با استفاده از API نسل اول) اجرا شود، میتوانید کنترلکننده رویداد چرخه عمر خود را به عنوان یک تابع واحد بنویسید که در رویداد 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 تکمیل شود، وظیفه را به زیروظایف تقسیم کنید و هر زیروظیفه را به ترتیب با قرار دادن کارها در صف با استفاده از متد TaskQueue.enqueue() در Admin SDK انجام دهید.
برای مثال، فرض کنید میخواهید دادههای 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 مشاهده کنند.
تکمیل موفقیتآمیز و خطاهای غیرمهلک
برای گزارش اتمام موفقیتآمیز و خطاهای غیرمهلک (خطاهایی که افزونه را در حالت غیرفعال قرار نمیدهند)، از متد زمان اجرای افزونه setProcessingState() در Admin SDK استفاده کنید:
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
برای جزئیات بیشتر در مورد این پارامترها، به بخش پیکربندی صفهای وظایف ابری در اسناد گوگل کلود مراجعه کنید.
سعی نکنید پارامترهای صف وظایف را با ارسال آنها به 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(
// ...
);
ویژگی taskQueueTrigger در extension.yaml تنها راه برای پیکربندی صفهای وظایف یک افزونه است.
مثالها
افزونههای رسمی storage-resize-images ، firestore-bigquery-export و firestore-translate-text همگی از کنترلکنندههای رویداد چرخه عمر برای پر کردن مجدد دادهها استفاده میکنند.