Rozszerzenie może zawierać Cloud Tasks funkcje które są wywoływane, gdy instancja rozszerzenia przechodzi przez dowolne z tych zdarzeń cyklu życia:
- Instalacja instancji rozszerzenia
- Aktualizacja instancji rozszerzenia do nowej wersji
- Zmiana konfiguracji instancji rozszerzenia
Jednym z najważniejszych zastosowań tej funkcji jest wypełnianie danych. Załóżmy
na przykład, że tworzysz rozszerzenie, które generuje miniatury
obrazów przesłanych do zasobnika Cloud Storage. Główna praca rozszerzenia
będzie wykonywana w funkcji wywoływanej przez zdarzenie onFinalize Cloud Storage.
Przetwarzane będą jednak tylko obrazy przesłane po zainstalowaniu rozszerzenia. Jeśli w rozszerzeniu uwzględnisz funkcję wywoływaną przez zdarzenie cyklu życia
onInstall, możesz też generować miniatury
istniejących obrazów po zainstalowaniu rozszerzenia.
Inne zastosowania wyzwalaczy zdarzeń cyklu życia:
- Automatyzacja konfiguracji po instalacji (tworzenie rekordów bazy danych, indeksowanie itp.)
- Automatyczna migracja danych podczas aktualizacji, jeśli musisz opublikować zmiany, które nie są zgodne z poprzednimi wersjami
Krótkotrwałe procedury obsługi zdarzeń cyklu życia
Jeśli zadanie może zostać wykonane w całości w
maksymalnym Cloud Functions czasie trwania (9
minut w przypadku interfejsu API pierwszej generacji), możesz napisać procedurę obsługi zdarzeń cyklu życia
jako pojedynczą funkcję, która jest wywoływana przez zdarzenie onDispatch kolejki zadań:
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).
});
Następnie w pliku extension.yaml rozszerzenia wykonaj te czynności:
Zarejestruj funkcję jako zasób rozszerzenia z ustawioną właściwością
taskQueueTrigger. Jeśli ustawisztaskQueueTriggerna pustą mapę ({}), Twoje rozszerzenie utworzy kolejkę Cloud Tasks z ustawieniami domyślnymi . Możesz też opcjonalnie dostosować te ustawienia.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: {}Zarejestruj funkcję jako procedurę obsługi co najmniej 1 zdarzenia cyklu życia:
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 extensionMożesz zarejestrować funkcje dla dowolnego z tych zdarzeń:
onInstall,onUpdateionConfigure. Wszystkie te zdarzenia są opcjonalne.-
Dodaj na przykład parametr taki jak ten:
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: falseA w funkcji, jeśli parametr jest ustawiony na
false, zakończ działanie: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. // ... });
Wykonywanie długotrwałych zadań
Jeśli zadanie nie może zostać wykonane w maksymalnym czasie trwania Cloud Functions,
podziel je na podzadania i wykonaj je kolejno, dodając
zadania do kolejki za pomocą TaskQueue.enqueue()
pakietu Admin SDK.
Załóżmy na przykład, że chcesz wypełnić dane Cloud Firestore. Możesz podzielić kolekcję dokumentów na fragmenty za pomocą kursorów zapytań. Po przetworzeniu fragmentu zwiększ przesunięcie początkowe i dodaj do kolejki kolejne wywołanie funkcji, jak pokazano poniżej:
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).
}
});
Dodaj funkcję do pliku extension.yaml zgodnie z opisem w
poprzedniej sekcji.
Stan raportowania
Gdy wszystkie funkcje przetwarzania zostaną zakończone (z powodzeniem lub z błędem), zgłoś stan zadania za pomocą metod środowiska wykonawczego rozszerzenia pakietu Admin SDK. Użytkownicy mogą zobaczyć ten stan na stronie z informacjami o rozszerzeniu w Firebase konsoli.
Pomyślne zakończenie i błędy niekrytyczne
Aby zgłosić pomyślne zakończenie i błędy niekrytyczne (błędy, które nie powodują, że rozszerzenie przestaje działać), użyj metody środowiska wykonawczego rozszerzenia setProcessingState() pakietu Admin SDK:
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setProcessingState(processingState, message);
Możesz ustawić te stany:
| Stany niekrytyczne | |
|---|---|
PROCESSING_COMPLETE |
Użyj, aby zgłosić pomyślne zakończenie zadania. Przykład: getExtensions().runtime().setProcessingState( "PROCESSING_COMPLETE", `Backfill complete. Successfully processed ${numSuccess} documents.` ); |
PROCESSING_WARNING |
Użyj, aby zgłosić częściowe powodzenie. Przykład: getExtensions().runtime().setProcessingState( "PROCESSING_WARNING", `Backfill complete. ${numSuccess} documents processed successfully.` + ` ${numFailed} documents failed to process. ${listOfErrors}.` + ` ${instructionsToFixTheProblem}` ); |
PROCESSING_FAILED |
Użyj, aby zgłosić błędy, które uniemożliwiają ukończenie zadania, ale nie powodują, że rozszerzenie przestaje działać. Przykład: getExtensions().runtime().setProcessingState( "PROCESSING_FAILED", `Backfill failed. ${errorMsg} ${optionalInstructionsToFixTheProblem}.` ); Aby zgłosić błędy, które powodują, że rozszerzenie przestaje działać, wywołaj
|
NONE |
Użyj, aby wyczyścić stan zadania. Możesz też użyć tej opcji, aby wyczyścić
komunikat o stanie w konsoli (np. po upływie pewnego czasu od ustawienia getExtensions().runtime().setProcessingState("NONE"); |
Błędy krytyczne
Jeśli wystąpi błąd, który uniemożliwia działanie rozszerzenia (np. nie powiedzie się wymagane zadanie konfiguracji), zgłoś błąd krytyczny za pomocą setFatalError():
import { getExtensions } from "firebase-admin/extensions";
// ...
getExtensions().runtime().setFatalError(`Post-installation setup failed. ${errorMessage}`);
Dostosowywanie kolejki zadań
Jeśli ustawisz właściwość taskQueueTrigger na {}, rozszerzenie utworzy kolejkę Cloud Tasks z ustawieniami domyślnymi po zainstalowaniu instancji rozszerzenia. Możesz też dostosować limity współbieżności kolejki zadań i zachowanie podczas ponawiania, podając konkretne wartości:
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
Szczegółowe informacje o tych parametrach znajdziesz w dokumentacji Google Cloud w artykule Konfigurowanie kolejek Cloud Tasks.
Nie próbuj określać parametrów kolejki zadań, przekazując je do taskQueue().
Te ustawienia są ignorowane na rzecz konfiguracji w extension.yaml i domyślnych ustawień konfiguracji.
Na przykład to nie zadziała:
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(
// ...
);
Właściwość taskQueueTrigger w extension.yaml to jedyny sposób na skonfigurowanie kolejek zadań rozszerzenia.
Przykłady
Oficjalne rozszerzenia storage-resize-images,
firestore-bigquery-export,
i firestore-translate-text
używają procedur obsługi zdarzeń cyklu życia do wypełniania danych.