Ваше расширение может включать в себя функции 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
значение {}
, ваше расширение подготовит очередь облачных задач с настройками по умолчанию при установке экземпляра расширения. Альтернативно вы можете настроить ограничения параллелизма очереди задач и поведение повторных попыток, указав определенные значения:
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.
Не пытайтесь указать параметры очереди задач, передав их в 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
используют обработчики событий жизненного цикла для обратного заполнения данных.