La tua estensione può includere funzioni Cloud Tasks che si attivano quando un'istanza di estensione attraversa uno dei seguenti eventi del ciclo di vita:
- Viene installata un'istanza dell'estensione
- Un'istanza dell'estensione viene aggiornata a una nuova versione
- La configurazione di un'istanza di estensione viene modificata
Uno dei casi d'uso più importanti di questa funzionalità è il backfill dei dati . Ad esempio, supponi di creare un'estensione che generi anteprime in miniatura delle immagini caricate in un bucket Cloud Storage. Il lavoro principale della tua estensione verrebbe svolto in una funzione attivata dall'evento onFinalize
Cloud Storage. Tuttavia, verranno elaborate solo le immagini caricate dopo l'installazione dell'estensione. Includendo nella tua estensione una funzione attivata dall'evento del ciclo di vita onInstall
, potresti anche generare anteprime in miniatura di qualsiasi immagine esistente quando l'estensione viene installata.
Alcuni altri casi d'uso degli attivatori di eventi del ciclo di vita includono:
- Automatizza la configurazione post-installazione (creazione di record di database, indicizzazione, ecc.)
- Se devi pubblicare modifiche incompatibili con le versioni precedenti, esegui la migrazione automatica dei dati durante l'aggiornamento
Gestori di eventi del ciclo di vita di breve durata
Se la tua attività può essere eseguita completamente entro la durata massima di Cloud Functions (9 minuti utilizzando l'API di prima generazione), puoi scrivere il gestore eventi del ciclo di vita come una singola funzione che si attiva sull'evento onDispatch
della coda delle attività:
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).
});
Quindi, nel file extension.yaml
della tua estensione, procedi come segue:
Registra la tua funzione come risorsa di estensione con il set di proprietà
taskQueueTrigger
. Se impostitaskQueueTrigger
sulla mappa vuota ({}
), la tua estensione eseguirà il provisioning di una coda Cloud Tasks utilizzando le impostazioni predefinite; facoltativamente è possibile ottimizzare queste impostazioni .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: {}
Registra la tua funzione come gestore per uno o più eventi del ciclo di vita:
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
È possibile registrare le funzioni per uno qualsiasi dei seguenti eventi:
onInstall
,onUpdate
eonConfigure
. Tutti questi eventi sono facoltativi.Consigliato : se l'attività di elaborazione non è necessaria per il funzionamento dell'estensione, aggiungi un parametro configurato dall'utente che consenta agli utenti di scegliere se abilitarla.
Ad esempio, aggiungi un parametro come il seguente:
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
E nella tua funzione, se il parametro è impostato su
false
, esci presto: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. // ... });
Esecuzione di attività di lunga durata
Se l'attività non può essere completata entro la durata massima di Cloud Functions, suddividi l'attività in attività secondarie ed esegui ciascuna attività secondaria in sequenza accodando i processi con il metodo TaskQueue.enqueue()
di Admin SDK.
Ad esempio, supponi di voler eseguire il backfill dei dati di Cloud Firestore. Puoi dividere la raccolta di documenti in blocchi utilizzando i cursori di query . Dopo aver elaborato un pezzo, avanzare l'offset iniziale e accodare un'altra invocazione di funzione come mostrato di seguito:
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).
}
});
Aggiungi la funzione alla tua extension.yaml
come descritto nella sezione precedente .
Stato della segnalazione
Una volta completate tutte le funzioni di elaborazione, con esito positivo o con un errore, segnala lo stato dell'attività utilizzando i metodi di runtime dell'estensione di Admin SDK. Gli utenti possono visualizzare questo stato nella pagina dei dettagli dell'estensione nella console Firebase.
Completamento riuscito ed errori non fatali
Per segnalare il completamento riuscito e gli errori non irreversibili (errori che non mettono l'estensione in uno stato non funzionante), utilizza il metodo di runtime dell'estensione setProcessingState()
di Admin SDK:
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setProcessingState(processingState, message);
È possibile impostare i seguenti stati:
Stati non fatali | |
---|---|
PROCESSING_COMPLETE | Utilizzare per segnalare il completamento corretto dell'attività. Esempio: getExtensions().runtime().setProcessingState( "PROCESSING_COMPLETE", `Backfill complete. Successfully processed ${numSuccess} documents.` ); |
PROCESSING_WARNING | Utilizzare per segnalare un successo parziale. Esempio: getExtensions().runtime().setProcessingState( "PROCESSING_WARNING", `Backfill complete. ${numSuccess} documents processed successfully.` + ` ${numFailed} documents failed to process. ${listOfErrors}.` + ` ${instructionsToFixTheProblem}` ); |
PROCESSING_FAILED | Utilizzare per segnalare errori che impediscono il completamento dell'attività, ma non lasciano l'estensione inutilizzabile. Esempio: getExtensions().runtime().setProcessingState( "PROCESSING_FAILED", `Backfill failed. ${errorMsg} ${optionalInstructionsToFixTheProblem}.` ); Per segnalare errori che lasciano l'estensione inutilizzabile, chiama |
NONE | Utilizzare per cancellare lo stato dell'attività. Facoltativamente puoi usarlo per cancellare il messaggio di stato dalla console (ad esempio, dopo che è trascorso un certo periodo di tempo dall'impostazione di getExtensions().runtime().setProcessingState("NONE"); |
Errori fatali
Se si verifica un errore che impedisce il funzionamento dell'estensione, ad esempio il fallimento di un'attività di configurazione richiesta, segnala l'errore irreversibile con setFatalError()
:
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setFatalError(`Post-installation setup failed. ${errorMessage}`);
Ottimizzazione della coda delle attività
Se imposti la proprietà taskQueueTrigger
su {}
, la tua estensione eseguirà il provisioning di una coda Cloud Tasks con le impostazioni predefinite quando viene installata un'istanza di estensione. In alternativa, puoi ottimizzare i limiti di concorrenza della coda di attività e il comportamento dei tentativi fornendo valori specifici:
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
Vedi Configurare le code di Cloud Tasks nella documentazione di Google Cloud per i dettagli su questi parametri.
Esempi
Le storage-resize-images
, firestore-bigquery-export
e firestore-translate-text
utilizzano tutte gestori di eventi del ciclo di vita per eseguire il backfill dei dati.