L'estensione può includere funzioni Cloud Tasks che si attivano quando un'istanza di un'estensione esegue uno dei seguenti processi: degli eventi del ciclo di vita:
- È stata installata un'istanza dell'estensione
- Un'istanza dell'estensione viene aggiornata a una nuova versione
- La configurazione di un'istanza dell'estensione è stata modificata
Uno dei casi d'uso più importanti di questa funzionalità è il backfill dei dati. Per
Ad esempio, supponiamo che tu stia creando un'estensione che genera anteprime delle miniature.
di immagini caricate in un bucket Cloud Storage. L'attività principale della tua estensione
verrebbe eseguito in una funzione attivata dall'evento Cloud Storage onFinalize
.
Tuttavia, verranno usate solo le immagini caricate dopo l'installazione dell'estensione.
elaborati. Se includi nell'estensione una funzione attivata dal
onInstall
evento del ciclo di vita, puoi anche generare anteprime in miniatura di qualsiasi
immagini esistenti quando l'estensione è installata.
Alcuni altri casi d'uso degli attivatori di eventi del ciclo di vita includono:
- Automatizzare la configurazione post-installazione (creazione di record di database, indicizzazione ecc.)
- Se devi pubblicare modifiche non compatibili con le versioni precedenti, esegui automaticamente la migrazione dati all'aggiornamento
Gestori di eventi del ciclo di vita a breve esecuzione
Se l'attività può essere eseguita completamente
durata massima Cloud Functions (9
minuti utilizzando l'API di prima generazione), puoi scrivere il tuo evento del ciclo di vita
come singola funzione che si attiva sull'evento onDispatch
della coda di 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
dell'estensione, procedi nel seguente modo:
Registra la tua funzione come risorsa di estensione con
taskQueueTrigger
insieme di proprietà. Se impostitaskQueueTrigger
sulla mappa vuota ({}
), il tuo l'estensione eseguirà il provisioning di una coda Cloud Tasks utilizzando il valore predefinito impostazioni; puoi scegliere di 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
Puoi 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 attivarla.
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 funzione, se il parametro è impostato su
false
, esci in anticipo: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:
suddividere l'attività in attività secondarie ed eseguire ciascuna in sequenza accodando
job con TaskQueue.enqueue()
dell'SDK Admin
.
Ad esempio, supponi di voler eseguire il backfill dei dati Cloud Firestore. Puoi suddividono la raccolta di documenti in blocchi utilizzando i cursori di query. Dopo aver elaborato un blocco, avanza l'offset iniziale e accoda un altro blocco come illustrato 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 a extension.yaml
come descritto in
sezione precedente.
Stato dei report
Al termine di tutte le funzioni di elaborazione, con esito positivo o con un errore, segnala lo stato dell'attività utilizzando i metodi di runtime dell'estensione dell'SDK Amministrazione. Gli utenti possono vedere questo stato nella pagina dei dettagli dell'estensione nel Console Firebase.
Completamento riuscito ed errori non irreversibili
Per segnalare errori di completamento riuscito ed errori non irreversibili (errori che non inseriscono
l'estensione in uno stato non funzionale), utilizza la classe
Metodo di runtime dell'estensione setProcessingState()
:
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setProcessingState(processingState, message);
Puoi impostare i seguenti stati:
Stati non irreversibili | |
---|---|
PROCESSING_COMPLETE |
Da utilizzare per segnalare il completamento dell'attività. Esempio: getExtensions().runtime().setProcessingState( "PROCESSING_COMPLETE", `Backfill complete. Successfully processed ${numSuccess} documents.` ); |
PROCESSING_WARNING |
Da utilizzare per segnalare un buon esito parziale. Esempio: getExtensions().runtime().setProcessingState( "PROCESSING_WARNING", `Backfill complete. ${numSuccess} documents processed successfully.` + ` ${numFailed} documents failed to process. ${listOfErrors}.` + ` ${instructionsToFixTheProblem}` ); |
PROCESSING_FAILED |
Utilizzalo per segnalare gli errori che impediscono il completamento dell'attività, ma che non e lasciare l'estensione inutilizzabile. Esempio: getExtensions().runtime().setProcessingState( "PROCESSING_FAILED", `Backfill failed. ${errorMsg} ${optionalInstructionsToFixTheProblem}.` ); Per segnalare errori che rendono inutilizzabili l'estensione, chiama
|
NONE |
Utilizza questa opzione per cancellare lo stato dell'attività. Puoi facoltativamente utilizzarla per cancellare
il messaggio di stato dalla console (ad esempio, dopo un certo
è trascorso il tempo dall'impostazione di getExtensions().runtime().setProcessingState("NONE"); |
Errori irreversibili
Se si verifica un errore che impedisce il funzionamento dell'estensione, ad esempio
Ad esempio, un'attività di configurazione obbligatoria non riesce. Segnala l'errore irreversibile con
setFatalError()
:
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setFatalError(`Post-installation setup failed. ${errorMessage}`);
Ottimizzazione della coda di attività
Se imposti la proprietà taskQueueTrigger
su {}
, l'estensione verrà
eseguire il provisioning di una coda di Cloud Tasks con le impostazioni predefinite quando
dell'istanza di Compute Engine. In alternativa, puoi ottimizzare i limiti di concorrenza e il comportamento di ripetizione della coda di attività specificando 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.
Non provare a specificare parametri della coda di attività passandoli a taskQueue()
.
Queste impostazioni vengono ignorate a favore della configurazione in extension.yaml
e
i valori predefiniti della configurazione.
Ad esempio, questa operazione non andrà a buon fine:
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 proprietà taskQueueTrigger
in extension.yaml
è l'unico modo per eseguire la configurazione
le code di attività di un'estensione.
Esempi
Il link ufficiale storage-resize-images
,
firestore-bigquery-export
,
e firestore-translate-text
Tutte le estensioni utilizzano gestori di eventi del ciclo di vita per eseguire il backfill dei dati.