Su extensión puede incluir funciones de Cloud Tasks que se activan cuando una instancia de extensión pasa por cualquiera de los siguientes eventos del ciclo de vida:
- Se instala una instancia de la extensión.
- Una instancia de la extensión se actualiza a una nueva versión.
- Se cambia la configuración de una instancia de extensión.
Uno de los casos de uso más importantes de esta función es el reabastecimiento de datos . Por ejemplo, suponga que está creando una extensión que genera vistas previas en miniatura de las imágenes cargadas en un depósito de Cloud Storage. El trabajo principal de su extensión se realizaría en una función activada por el evento onFinalize
Cloud Storage. Sin embargo, solo se procesarán las imágenes cargadas después de instalar la extensión. Al incluir en su extensión una función activada por el evento del ciclo de vida onInstall
, también puede generar vistas previas en miniatura de cualquier imagen existente cuando se instala la extensión.
Algunos otros casos de uso de desencadenadores de eventos del ciclo de vida incluyen:
- Automatizar la configuración posterior a la instalación (creación de registros de bases de datos, indexación, etc.)
- Si tiene que publicar cambios incompatibles con versiones anteriores, migre automáticamente los datos al actualizar
Controladores de eventos de ciclo de vida de corta duración
Si su tarea puede ejecutarse completamente dentro de la duración máxima de Cloud Functions (9 minutos usando la API de primera generación), puede escribir su controlador de eventos de ciclo de vida como una función única que se activa en el evento onDispatch
de la cola de tareas:
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).
});
Luego, en el archivo extension.yaml
de su extensión, haga lo siguiente:
Registre su función como un recurso de extensión con la propiedad
taskQueueTrigger
establecida. Si configurataskQueueTrigger
en el mapa vacío ({}
), su extensión aprovisionará una cola de Cloud Tasks usando la configuración predeterminada; Opcionalmente, puede ajustar estas configuraciones .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: {}
Registre su función como controlador de uno o más eventos del ciclo de vida:
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
Puede registrar funciones para cualquiera de los siguientes eventos:
onInstall
,onUpdate
yonConfigure
. Todos estos eventos son opcionales.Recomendado : si la tarea de procesamiento no es necesaria para que su extensión funcione, agregue un parámetro configurado por el usuario que les permita elegir si habilitarla.
Por ejemplo, agregue un parámetro como el siguiente:
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
Y en su función, si el parámetro está configurado en
false
, salga temprano: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. // ... });
Realizar tareas de larga duración
Si su tarea no puede completarse dentro de la duración máxima de Cloud Functions, divida la tarea en subtareas y realice cada subtarea en secuencia poniendo en cola los trabajos con el método TaskQueue.enqueue()
del Admin SDK.
Por ejemplo, supongamos que desea reponer los datos de Cloud Firestore. Puede dividir la colección de documentos en fragmentos utilizando cursores de consulta . Después de procesar un fragmento, avance el desplazamiento inicial y ponga en cola otra invocación de función como se muestra a continuación:
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).
}
});
Agregue la función a su extension.yaml
como se describe en la sección anterior .
Estado del informe
Cuando finalicen todas sus funciones de procesamiento, ya sea exitosamente o con un error, informe el estado de la tarea utilizando los métodos de tiempo de ejecución de la extensión Admin SDK. Los usuarios pueden ver este estado en la página de detalles de la extensión en Firebase console.
Finalización exitosa y errores no fatales.
Para informar la finalización exitosa y errores no fatales (errores que no ponen la extensión en un estado no funcional), use el método de tiempo de ejecución de la extensión setProcessingState()
del SDK de administración:
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setProcessingState(processingState, message);
Puede configurar los siguientes estados:
Estados no fatales | |
---|---|
PROCESSING_COMPLETE | Úselo para informar la finalización exitosa de la tarea. Ejemplo: getExtensions().runtime().setProcessingState( "PROCESSING_COMPLETE", `Backfill complete. Successfully processed ${numSuccess} documents.` ); |
PROCESSING_WARNING | Úselo para informar un éxito parcial. Ejemplo: getExtensions().runtime().setProcessingState( "PROCESSING_WARNING", `Backfill complete. ${numSuccess} documents processed successfully.` + ` ${numFailed} documents failed to process. ${listOfErrors}.` + ` ${instructionsToFixTheProblem}` ); |
PROCESSING_FAILED | Úselo para informar errores que impiden que se complete la tarea, pero no deje la extensión inutilizable. Ejemplo: getExtensions().runtime().setProcessingState( "PROCESSING_FAILED", `Backfill failed. ${errorMsg} ${optionalInstructionsToFixTheProblem}.` ); Para informar errores que dejan la extensión inutilizable, llame a |
NONE | Úselo para borrar el estado de la tarea. Opcionalmente, puede usar esto para borrar el mensaje de estado de la consola (por ejemplo, después de que haya pasado un tiempo desde que se configuró getExtensions().runtime().setProcessingState("NONE"); |
Errores fatales
Si se produce un error que impide que la extensión funcione (por ejemplo, si falla una tarea de configuración requerida), informe el error fatal con setFatalError()
:
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setFatalError(`Post-installation setup failed. ${errorMessage}`);
Ajustando la cola de tareas
Si configura la propiedad taskQueueTrigger
en {}
, su extensión aprovisionará una cola de Cloud Tasks con la configuración predeterminada cuando se instale una instancia de extensión. Como alternativa, puede ajustar los límites de simultaneidad de la cola de tareas y reintentar el comportamiento proporcionando valores específicos:
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
Consulte Configurar colas de Cloud Tasks en los documentos de Google Cloud para obtener detalles sobre estos parámetros.
No intente especificar parámetros de la cola de tareas pasándolos a taskQueue()
. Estas configuraciones se ignoran en favor de la configuración en extension.yaml
y los valores predeterminados de configuración.
Por ejemplo, esto no funcionará:
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(
// ...
);
La propiedad taskQueueTrigger
en extension.yaml
es la única forma de configurar las colas de tareas de una extensión.
Ejemplos
Las extensiones oficiales storage-resize-images
, firestore-bigquery-export
y firestore-translate-text
utilizan controladores de eventos de ciclo de vida para reponer los datos.