Расширение может включать функции Cloud Tasks, которые активируются, когда экземпляр расширения проходит через любое из следующих событий жизненного цикла:
- Экземпляр расширения установлен.
- Экземпляр расширения обновлен до новой версии.
- Изменена конфигурация экземпляра расширения.
Один из наиболее важных вариантов использования этой функции – заполнение данных. Например, предположим, что вы создаете расширение, которое генерирует предварительный просмотр миниатюр изображений, загруженных в корзину Cloud Storage. Основная работа расширения будет выполняться в функции, запускаемой событием onFinalize Cloud Storage.
Однако обрабатываться будут только изображения, загруженные после установки расширения. Если вы добавите в расширение функцию, которая активируется событием жизненного цикла onInstall, то сможете генерировать уменьшенные изображения для предварительного просмотра любых существующих изображений при установке расширения.
Вот ещё несколько примеров использования триггеров событий жизненного цикла:
- Автоматизируйте настройку после установки (создание записей в базе данных, индексирование и т. д.).
- Если вам нужно опубликовать изменения, несовместимые с предыдущими версиями, настройте автоматический перенос данных при обновлении
Краткосрочные обработчики событий жизненного цикла
Если задача может быть полностью выполнена в течение максимальной продолжительности 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
Подробную информацию об этих параметрах можно найти в статье Настройка очередей Cloud Tasks в документации Google Cloud.
Не пытайтесь задать параметры очереди задач, передавая их в 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 используют обработчики событий жизненного цикла для заполнения данных.