Funkcje możesz wdrażać, usuwać i modyfikować za pomocą poleceń interfejsu wiersza poleceń Firebase lub ustawiając opcje środowiska wykonawczego w kodzie źródłowym funkcji.
Wdrażanie funkcji
Aby wdrożyć funkcje, uruchom to polecenie wiersza poleceń Firebase:
firebase deploy --only functions
Domyślnie wiersz poleceń Firebase wdraża wszystkie funkcje w Twoim źródle w tym samym czasie. Jeśli Twój projekt zawiera więcej niż 5 funkcji, zalecamy użycie parametru --only
z określonymi nazwami funkcji, aby wdrożyć tylko zmodyfikowane przez Ciebie funkcje. Wdrażanie konkretnych funkcji w ten sposób przyspiesza proces wdrażania i pomaga uniknąć przekroczenia limitów wdrażania. Przykład:
firebase deploy --only functions:addMessage,functions:makeUppercase
W przypadku wdrażania dużej liczby funkcji może dojść do przekroczenia limitu standardowego i pojawienia się komunikatów o błędach HTTP 429 lub 500. Aby tego uniknąć, stosuj funkcje w grupach liczących co najwyżej 10 elementów.
Pełną listę dostępnych poleceń znajdziesz w dokumentacji interfejsu wiersza poleceń Firebase.
Domyślnie interfejs wiersza poleceń Firebase szuka kodu źródłowego w folderze functions/
. Jeśli wolisz, możesz porządkować funkcje w bazach kodu lub w wielu zbiorach plików.
Usuwanie funkcji
Funkcję, która została już wdrożona, możesz usunąć na jeden z tych sposobów:
- wyraźnie w interfejsie wiersza poleceń Firebase za pomocą polecenia
functions:delete
. - wyraźnie w Google Cloud konsoli.
- domyślnie, usuwając funkcję ze źródła przed wdrożeniem.
Przed usunięciem funkcji z produkcji musisz potwierdzić wszystkie operacje usuwania.
Wyraźne usuwanie funkcji w CLI Firebase obsługuje wiele argumentów, a także grupy funkcji i pozwala określić funkcję działającą w określonym regionie. Możesz też zignorować prośbę o potwierdzenie.
# Delete all functions that match the specified name in all regions. firebase functions:delete myFunction
# Delete a specified function running in a specific region. firebase functions:delete myFunction --region us-east-1
# Delete more than one function firebase functions:delete myFunction myOtherFunction
# Delete a specified functions group. firebase functions:delete groupA
# Bypass the confirmation prompt. firebase functions:delete myFunction --force
Przy domyślnym usuwaniu funkcji firebase deploy
analizuje kod źródłowy i usuwa z wersji produkcyjnej wszystkie funkcje, które zostały usunięte z pliku.
Zmodyfikuj nazwę funkcji, region lub aktywator
Jeśli zmieniasz nazwy regionów lub ich inicjatory lub zmieniasz je w przypadku funkcji, które obsługują ruch produkcyjny, wykonaj czynności opisane w tym rozdziale, aby uniknąć utraty zdarzeń podczas modyfikacji. Zanim wykonasz te czynności, upewnij się, że Twoja funkcja jest idempotentna, ponieważ podczas zmiany zarówno nowa, jak i stara wersja funkcji będą uruchamiane w tym samym czasie.
Zmienianie nazwy funkcji
Aby zmienić nazwę funkcji, utwórz jej nową wersję ze zmienioną nazwą w źródle, a następnie uruchom 2 osobne polecenia wdrożeniowe. Pierwsze polecenie wdraża funkcję o nowej nazwie, a drugie usuwa wcześniej wdrożony wariant. Jeśli na przykład masz wywoływany przez HTTP webhook, który chcesz przemianować, zmodyfikuj kod w ten sposób:
Node.js
// before
const {onRequest} = require('firebase-functions/v2/https');
exports.webhook = onRequest((req, res) => {
res.send("Hello");
});
// after
const {onRequest} = require('firebase-functions/v2/https');
exports.webhookNew = onRequest((req, res) => {
res.send("Hello");
});
Python
# before
from firebase_functions import https_fn
@https_fn.on_request()
def webhook(req: https_fn.Request) -> https_fn.Response:
return https_fn.Response("Hello world!")
# after
from firebase_functions import https_fn
@https_fn.on_request()
def webhook_new(req: https_fn.Request) -> https_fn.Response:
return https_fn.Response("Hello world!")
Następnie uruchom te polecenia, aby wdrożyć nową funkcję:
# Deploy new function firebase deploy --only functions:webhookNew # Wait until deployment is done; now both functions are running # Delete webhook firebase functions:delete webhook
Zmiana regionu lub regionów funkcji
Jeśli zmieniasz określone regiony funkcji, która obsługuje ruch produkcyjny, możesz zapobiec utracie zdarzeń, wykonując te czynności w następującej kolejności:
- Zmień nazwę funkcji i w razie potrzeby zmień jej region lub regiony.
- Wdróż przemianowaną funkcję, co spowoduje tymczasowe uruchomienie tego samego kodu w obu zestawach regionów.
- Usuń poprzednią funkcję.
Jeśli na przykład masz funkcję wyzwalaną przez Cloud Firestore, która obecnie znajduje się w domyślnym regionie funkcji us-central1
, i chcesz ją przenieść do asia-northeast1
, musisz najpierw zmodyfikować kod źródłowy, aby zmienić nazwę funkcji i poprawić region.
Node.js
// before
exports.firestoreTrigger = onDocumentCreated(
"my-collection/{docId}",
(event) => {},
);
// after
exports.firestoreTriggerAsia = onDocumentCreated(
{
document: "my-collection/{docId}",
region: "asia-northeast1",
},
(event) => {},
);
Zaktualizowany kod powinien określać prawidłowy filtr zdarzeń (w tym przypadku document
) wraz z regionem. Więcej informacji znajdziesz w sekcji lokalizacje Cloud Functions.
Python
# Before
@firestore_fn.on_document_created("my-collection/{docId}")
def firestore_trigger(event):
pass
# After
@firestore_fn.on_document_created("my-collection/{docId}",
region="asia-northeast1")
def firestore_trigger_asia(event):
pass
Następnie wdróż, wykonując te czynności:
firebase deploy --only functions:firestoreTriggerAsia
Teraz są uruchomione 2 identyczne funkcje: firestoreTrigger
w kontekście us-central1
i firestoreTriggerAsia
w kontekście asia-northeast1
.
Następnie usuń firestoreTrigger
:
firebase functions:delete firestoreTrigger
Teraz jest tylko jedna funkcja – firestoreTriggerAsia
, która działa w ramach asia-northeast1
.
Zmień typ aktywatora funkcji
W miarę rozwijania wdrożenia Cloud Functions for Firebase może się okazać, że z różnych powodów trzeba zmienić typ wyzwalacza funkcji. Możesz na przykład zmienić jeden typ zdarzenia Firebase Realtime Database lub Cloud Firestore na inny.
Nie można zmienić typu zdarzenia funkcji, po prostu zmieniając kod źródłowy i uruchamiając firebase deploy
. Aby uniknąć błędów, zmień typ okna funkcji:
- Zmodyfikuj kod źródłowy, aby uwzględnić nową funkcję z wybranym typem wyzwalacza.
- Wdroż funkcję, co spowoduje tymczasowe uruchomienie zarówno starej, jak i nowej funkcji.
- Usuń starą funkcję z produkcji za pomocą interfejsu wiersza poleceń Firebase.
Jeśli np. masz funkcję, która została aktywowana po usunięciu obiektu, a potem masz włączoną obsługę wersji obiektu i chcesz zamiast tego zasubskrybować zdarzenie archiwum, najpierw zmień nazwę funkcji i zmień jej typ na nowy typ aktywatora.
Node.js
// before
const {onObjectDeleted} = require("firebase-functions/v2/storage");
exports.objectDeleted = onObjectDeleted((event) => {
// ...
});
// after
const {onObjectArchived} = require("firebase-functions/v2/storage");
exports.objectArchived = onObjectArchived((event) => {
// ...
});
Python
# before
from firebase_functions import storage_fn
@storage_fn.on_object_deleted()
def object_deleted(event):
# ...
# after
from firebase_functions import storage_fn
@storage_fn.on_object_archived()
def object_archived(event):
# ...
Następnie utwórz nową funkcję, zanim usuniesz starą:
# Create new function objectArchived firebase deploy --only functions:objectArchived # Wait until deployment is done; now both objectDeleted and objectArchived are running # Delete objectDeleted firebase functions:delete objectDeleted
Ustaw opcje środowiska wykonawczego
Cloud Functions for Firebase umożliwia wybranie opcji czasu wykonywania, takich jak wersja środowiska wykonawczego Node.js i czas oczekiwania na wykonanie funkcji, alokacja pamięci oraz minimalna i maksymalna liczba wystąpień funkcji.
Zgodnie ze sprawdzoną metodą te opcje (z wyjątkiem wersji Node.js) powinny być ustawiane w obiekcie konfiguracji w kodzie funkcji. Ten obiekt RuntimeOptions
jest źródłem informacji o opcjach czasu wykonywania funkcji i zastąpi opcje ustawione za pomocą dowolnej innej metody (np. w konsoli Google Cloud lub w interfejsie wiersza poleceń gcloud).
Jeśli Twój proces rozwoju obejmuje ręczne ustawianie opcji czasu wykonywania w konsoli Google Cloud lub interfejsie wiersza poleceń gcloud i nie chcesz, aby te wartości były zastępowane przy każdym wdrożeniu, ustaw opcję preserveExternalChanges
na true
.
Gdy ta opcja jest ustawiona na true
, Firebase scala opcje środowiska wykonawczego określone w kodzie z ustawieniami obecnie wdrożonej wersji funkcji z tym priorytetem:
- Opcja jest ustawiona w kodzie funkcji: zastąpij zmiany zewnętrzne.
- Opcja jest ustawiona na
RESET_VALUE
w kodzie funkcji: zastąpij zmiany zewnętrzne wartością domyślną. - Opcja nie jest ustawiona w kodzie funkcji, ale jest ustawiona w obecnie wdrożonej funkcji. Użyj opcji określonej we wdrożonej funkcji.
Nie zalecamy używania opcji preserveExternalChanges: true
w większości scenariuszy, ponieważ kod nie będzie już pełnym źródłem informacji o opcjach środowiska wykonawczego funkcji. Jeśli go używasz, wyświetl pełną konfigurację funkcji w konsoli Google Cloud lub za pomocą interfejsu wiersza poleceń gcloud.
Ustawianie wersji Node.js
Pakiet SDK Firebase dla Cloud Functions umożliwia wybór środowiska wykonawczego Node.js. Możesz uruchamiać wszystkie funkcje w projekcie wyłącznie w środowisku wykonawczym odpowiadającym jednej z tych obsługiwanych wersji Node.js:
- Node.js 22 (wersja przedpremierowa)
- Node.js 20
- Node.js 18
Wersje Node.js 14 i 16 zostały wycofane i zostaną wyłączone na początku 2025 r. Wdrażanie z tymi wycofanymi wersjami jest wyłączone.
Aby ustawić wersję Node.js:
Wersję możesz ustawić w polu engines
w pliku package.json
, który został utworzony w katalogu functions/
podczas inicjalizacji.
Aby na przykład używać tylko wersji 18, w pliku package.json
zmodyfikuj ten wiersz:
"engines": {"node": "20"}
Jeśli używasz menedżera pakietów Yarn lub masz inne wymagania dotyczące pola engines
, możesz ustawić środowisko wykonawcze pakietu SDK Firebase dla Cloud Functions w firebase.json
:
{
"functions": {
"runtime": "nodejs18" // or nodejs20
}
}
CLI używa wartości ustawionej w parametrye firebase.json
zamiast wartości lub zakresu ustawionego oddzielnie w parametrye package.json
.
Uaktualnianie środowiska wykonawczego Node.js
Aby uaktualnić środowisko wykonawcze Node.js:
- Upewnij się, że Twój projekt jest objęty abonamentem Blaze.
- Upewnij się, że używasz interfejsu wiersza poleceń Firebase w wersji 11.18.0 lub nowszej.
- Zmień wartość
engines
w plikupackage.json
utworzonym w katalogufunctions/
podczas inicjowania. Jeśli na przykład przechodzisz z wersji 18 na wersję 20, wpis powinien wyglądać tak:"engines": {"node": "20"}
- Opcjonalnie możesz przetestować zmiany za pomocą Firebase Local Emulator Suite.
- ponownie wdrożyć wszystkie funkcje.
Ustawianie wersji Pythona
Pakiet Firebase SDK w wersji Cloud Functions 12.0.0 lub nowszej umożliwia wybranie środowiska wykonawczego Pythona. Ustaw wersję środowiska wykonawczego w pliku firebase.json
, jak pokazano poniżej:
{
"functions": {
"runtime": "python310" // or python311
}
}
Kontrolowanie zachowania przy skalowaniu
Domyślnie Cloud Functions for Firebase skaluje liczbę uruchomionych instancji na podstawie liczby żądań przychodzących, a w czasie zmniejszonego ruchu może zmniejszyć liczbę instancji do 0. Jeśli jednak Twoja aplikacja wymaga krótszego czasu oczekiwania i chcesz ograniczyć liczbę uruchomień „na zimno”, możesz zmienić to domyślne działanie, określając minimalną liczbę instancji kontenera, które mają być utrzymywane w gotowości do obsługi żądań.
Podobnie możesz ustawić maksymalną liczbę, aby ograniczyć skalowanie instancji w odpowiedzi na przychodzące żądania. Użyj tego ustawienia, aby kontrolować koszty lub ograniczyć liczbę połączeń z usługą wspierającą, np. z bazą danych.
Za pomocą tych ustawień i ustawienia wielozadaniowość (nowe w drugiej generacji) możesz kontrolować i dostosowywać zachowanie skalowania funkcji. Charakter aplikacji i jej funkcje determinują, które ustawienia są najbardziej opłacalne i przynoszą najlepszą wydajność.
W przypadku niektórych aplikacji o małej liczbie użytkowników optymalna jest opcja z niższym wykorzystaniem procesora bez obsługi wielu wątków. W przypadku innych usług, w których uruchomienia „na zimno” stanowią poważny problem, ustawienie wysokiej współbieżności i minimalnej liczby instancji oznacza, że zestaw instancji jest zawsze utrzymywany w gotowości, aby obsługiwać duże wzrosty natężenia ruchu.
W przypadku mniejszych aplikacji, które mają niewielką liczbę wizyt, ustawienie niskiej maksymalnej liczby instancji przy dużej liczbie jednoczesnych użytkowników pozwala aplikacji obsługiwać szczyty ruchu bez generowania nadmiernych kosztów. Pamiętaj jednak, że jeśli wartość maksymalnej liczby instancji jest zbyt niska, prośby mogą zostać odrzucone po osiągnięciu limitu.
Zezwalanie na równoczesne żądania
W usłudze Cloud Functions for Firebase (pierwszej generacji) każda instancja mogła obsługiwać tylko jedno żądanie naraz, więc zachowanie skalowania było ustawiane tylko za pomocą ustawień minimalnej i maksymalnej liczby instancji.
Oprócz kontroli liczby instancji w Cloud Functions for Firebase (2 generacji) możesz też za pomocą opcji concurrency
kontrolować liczbę żądań, które może obsługiwać każda instancja w tym samym czasie. Domyślna wartość równoczesności to 80, ale możesz ustawić dowolną liczbę całkowitą z zakresu od 1 do 1000.
Funkcje z wyższymi ustawieniami równoległości mogą absorbować skok natężenia ruchu bez uruchamiania na zimno, ponieważ każda instancja prawdopodobnie ma pewien zapas. Jeśli instancja jest skonfigurowana tak, aby obsługiwać do 50 jednoczesnych żądań, ale obecnie obsługuje tylko 25, może obsłużyć 25 dodatkowych żądań bez konieczności uruchamiania nowej instancji. Z kolei przy ustawieniu równoczesności równym 1 taki wzrost liczby żądań może doprowadzić do 25 uruchomień „na zimno”.
Ten uproszczony scenariusz pokazuje potencjalne zwiększenie wydajności dzięki równoległości. W rzeczywistości skalowanie działania w celu optymalizacji wydajności i ograniczania „zimnych uruchomień” przy użyciu równoczesności jest bardziej złożone. Równoległość w Cloud Functions for Firebase drugiej generacji jest obsługiwana przez Cloud Run i podlega regułom Cloud Run dotyczącym autoskalowania instancji kontenera.
Podczas eksperymentowania z wyższymi ustawieniami równoległości w Cloud Functions for Firebase(2 generacji) pamiętaj o tych kwestiach:
- Aby zapewnić optymalną wydajność, wyższe ustawienia równoległości mogą wymagać większego wykorzystania procesora i pamięci RAM, aż do osiągnięcia praktycznego limitu. Funkcja, która wykonuje intensywne przetwarzanie obrazów lub filmów, może nie mieć zasobów do obsługi 1000 równoczesnych żądań, nawet jeśli ustawienia procesora i pamięci RAM są zmaksymalizowane.
- Ponieważ Cloud Functions for Firebase (2 generacji) korzysta z Cloud Run, możesz też zapoznać się z instrukcjami Google Cloud dotyczącymi optymalizacji współbieżności.
- Zanim przełączysz się na korzystanie z wielozadaności w produkcji, dokładnie przetestuj ją w środowisku testowym.
Utrzymuj minimalną liczbę instancji w gotowości
Możesz ustawić minimalną liczbę instancji dla funkcji w kodzie źródłowym. Na przykład ta funkcja ustawia minimalną liczbę instancji na 5, aby utrzymać je w stanie gotowości:
Node.js
const { onCall } = require("firebase-functions/v2/https");
exports.getAutocompleteResponse = onCall(
{
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
},
(event) => {
// Autocomplete user’s search term
}
);
Python
@https_fn.on_call(min_instances=5)
def get_autocomplete_response(event: https_fn.CallableRequest) -> https_fn.Response:
Podczas określania minimalnej liczby instancji należy wziąć pod uwagę te kwestie:
- Jeśli Cloud Functions for Firebase zwiększy skalę aplikacji powyżej Twojego ustawienia, uruchomienie „na zimno” będzie się odbywać w przypadku każdego wystąpienia powyżej tego progu.
- Uruchomienia „na zimno” mają największy wpływ na aplikacje z nieregularnym ruchem. Jeśli ruch w Twojej aplikacji jest nieregularny i ustawisz wartość wystarczająco wysoką, aby zmniejszyć liczbę zimnych uruchomień przy każdym wzroście natężenia ruchu, zauważysz znacznie krótszy czas oczekiwania. W przypadku aplikacji o stalej liczbie wizyt uruchomienia „na zimno” prawdopodobnie nie mają większego wpływu na wydajność.
Ustawienie minimalnej liczby instancji może być przydatne w środowiskach produkcyjnych, ale zazwyczaj należy go unikać w środowiskach testowych. Aby zmniejszyć liczbę instancji do zera w projekcie testowym, ale nadal ograniczać uruchomienia „na zimno” w projekcie produkcyjnym, możesz ustawić minimalną liczbę instancji w skonfigurowanej konfiguracji:
Node.js
const functions = require('firebase-functions/v1'); const { defineInt, defineString } = require('firebase-functions/params'); // Define some parameters const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES'); const welcomeMessage = defineString('WELCOME_MESSAGE'); // To use configured parameters inside the config for a function, provide them // directly. To use them at runtime, call .value() on them. export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest( (req, res) => { res.send(`${welcomeMessage.value()}! I am a function.`); } );
Python
MIN_INSTANCES = params.IntParam("HELLO_WORLD_MININSTANCES") WELCOME_MESSAGE = params.StringParam("WELCOME_MESSAGE") @https_fn.on_request(min_instances=MIN_INSTANCES.value()) def get_autocomplete_response(event: https_fn.Request) -> https_fn.Response: return https_fn.Response(f"{WELCOME_MESSAGE.value()} I'm a function.")
Ograniczanie maksymalnej liczby instancji funkcji
W kodzie źródłowym funkcji możesz ustawić wartość maksymalnej liczby wystąpień. Na przykład ta funkcja ustawia limit 100 wystąpieni, aby nie przeciążać hipotetycznej starszej bazy danych:
Node.js
const { onMessagePublished } = require("firebase-functions/v2/pubsub");
exports.mirrorevents = onMessagePublished(
{ topic: "topic-name", maxInstances: 100 },
(event) => {
// Connect to legacy database
}
);
Python
@pubsub_fn.on_message_published(topic="topic-name", max_instances=100)
def mirrorevents(event: pubsub_fn.CloudEvent):
# Connect to legacy database
Jeśli funkcja HTTP zostanie zwiększona do maksymalnej liczby instancji, nowe żądania są umieszczane w kolejce na 30 sekund, a następnie odrzucane z kodem odpowiedzi 429 Too Many Requests
, jeśli do tego czasu nie będzie dostępnej instancji.
Aby dowiedzieć się więcej o sprawdzonych metodach korzystania z ustawień maksymalnej liczby instancji, zapoznaj się z tymi sprawdzonymi metodami konfigurowania maksymalnej liczby instancji.
Ustaw limit czasu i przydział pamięci
W niektórych przypadkach funkcje mogą mieć specjalne wymagania dotyczące długiej wartości limitu czasu lub dużej ilości pamięci. Wartości te możesz ustawić w konsoli Google Cloud lub w kodzie źródłowym funkcji (tylko w Firebase).
Aby skonfigurować przydział pamięci i limit czasu w kodzie źródłowym funkcji, użyj opcji globalnych dotyczących pamięci i limitu czasu w sekundach, aby dostosować maszynę wirtualną, na której działają funkcje. Na przykład funkcja Cloud Storage zużywa 1 GiB pamięci i przestaje działać po 300 sekundach:
Node.js
exports.convertLargeFile = onObjectFinalized({
timeoutSeconds: 300,
memory: "1GiB",
}, (event) => {
// Do some complicated things that take a lot of memory and time
});
Python
@storage_fn.on_object_finalized(timeout_sec=300, memory=options.MemoryOption.GB_1)
def convert_large_file(event: storage_fn.CloudEvent):
# Do some complicated things that take a lot of memory and time.
Maksymalna wartość limitu czasu to 540
, czyli 9 minut.
Aby ustawić przydział pamięci i limit czasu w konsoli Google Cloud:
- W konsoli Google Cloud wybierz Cloud Functions for Firebase w menu po lewej stronie.
- Wybierz funkcję, klikając jej nazwę na liście funkcji.
- W menu u góry kliknij ikonę Edytuj.
- W menu Przydzielona pamięć wybierz przydział pamięci.
- Kliknij Więcej, aby wyświetlić opcje zaawansowane, i wpisz liczbę sekund w polu tekstowym Limit czasu.
- Aby zaktualizować funkcję, kliknij Zapisz.
Zastąp domyślne ustawienia procesora
Każda funkcja w Cloud Functions for Firebase (2 generacji) przydziela maksymalnie 2 GB pamięci, a domyślnie korzysta z 1 procesora. Następnie liczba procesorów zwiększa się do 2 w przypadku 4 i 8 GB. Pamiętaj, że to działanie znacznie różni się od domyślnego działania funkcji pierwszej generacji, co może prowadzić do nieznacznie wyższych kosztów funkcji o małej ilości pamięci, jak pokazano w następującej tabeli:
Przydzielona pamięć RAM | Wersja 1. Domyślny procesor (ułamkowy) | Procesor domyślny wersji 2 | Podwyżka ceny za ms |
---|---|---|---|
128 MB | 1/12 | 1 | 10,5× |
256 MB | 1/6 | 1 | 5,3 razy |
512 MB | 1/3 | 1 | 2,7x |
1 GB | 7/12 | 1 | 1,6x |
2 GB | 1 | 1 | 1x |
4 GB | 2 | 2 | 1x |
8 GB | 2 | 2 | 1x |
16 GB | Nie dotyczy | 4 | Nie dotyczy |
Jeśli wolisz działanie 1 generacji w przypadku funkcji 2 generacji, ustaw wartości domyślne 1 generacji jako opcję globalną:
Node.js
// Turn off Firebase defaults
setGlobalOptions({ cpu: 'gcf_gen1' });
Python
# Use 1st gen behavior
set_global_options(cpu="gcf_gen1")
W przypadku funkcji wymagających dużej mocy obliczeniowej funkcje 2 generacji umożliwiają konfigurowanie dodatkowego procesora. Możesz zwiększyć moc procesora dla poszczególnych funkcji:
Node.js
// Boost CPU in a function:
export const analyzeImage = onObjectFinalized({ cpu: 2 }, (event) => {
// computer vision goes here
});
Python
# Boost CPU in a function:
@storage_fn.on_object_finalized(cpu=2)
def analyze_image(event: storage_fn.CloudEvent):
# computer vision goes here