Estendi Datastore con Cloud Functions (2nd gen)

Con Cloud Functions ed Eventarc, puoi eseguire il deployment del codice per gestire gli eventi attivati dalle modifiche nel database Firestore in modalità Datastore. In questo modo puoi aggiungere funzionalità lato server senza utilizzare i tuoi server.

Trigger in modalità Datastore

Eventarc supporta i seguenti trigger di eventi Firestore in modalità Datastore per consentirti di creare gestori Cloud Functions (2nd gen) collegati a Firestore in eventi in modalità Datastore:

Tipo di evento Trigger
google.cloud.datastore.entity.v1.created Attivato quando un'entità viene scritta per la prima volta.
google.cloud.datastore.entity.v1.updated Si attiva quando un'entità esiste già e ha un valore modificato.
google.cloud.datastore.entity.v1.deleted Attivato quando viene eliminata un'entità.
google.cloud.datastore.entity.v1.written Si attiva quando vengono attivati created, updated o deleted.
google.cloud.datastore.entity.v1.created.withAuthContext Uguale a created, ma con l'aggiunta delle informazioni di autenticazione.
google.cloud.datastore.entity.v1.updated.withAuthContext Uguale a updated, ma con l'aggiunta delle informazioni di autenticazione.
google.cloud.datastore.entity.v1.deleted.withAuthContext Uguale a deleted, ma con l'aggiunta delle informazioni di autenticazione.
google.cloud.datastore.entity.v1.written.withAuthContext Uguale a written, ma con l'aggiunta delle informazioni di autenticazione.

I trigger di eventi in modalità Datastore rispondono solo alle modifiche delle entità. Un aggiornamento di un'entità in modalità Datastore in cui i dati non vengono modificati (scrittura automatica) non genera un evento di aggiornamento o scrittura. Non puoi generare eventi solo per proprietà specifiche.

Includi il contesto di autenticazione nell'evento

Per includere informazioni di autenticazione aggiuntive sull'evento, utilizza un attivatore di eventi con l'estensione withAuthContext. Questa estensione aggiunge ulteriori informazioni sull'entità che ha attivato l'evento. Aggiunge gli attributi authtype e authid oltre alle informazioni restituite nell'evento di base. Consulta il riferimento di authcontext per ulteriori informazioni sui valori degli attributi.

Scrivere una funzione attivata da entità

Per scrivere una funzione che risponda a Firestore in eventi in modalità Datastore, preparati a specificare quanto segue durante il deployment:

  • un tipo di evento trigger
  • un filtro di eventi di trigger per selezionare le entità associate alla funzione
  • il codice della funzione da eseguire

Filtri di eventi di trigger

Quando specifichi un filtro eventi, puoi indicare una corrispondenza esatta di entità o un pattern del percorso. Utilizza un pattern di percorso per abbinare più entità con i caratteri jolly * o **.

Ad esempio, puoi specificare una corrispondenza esatta dell'entità per rispondere alle modifiche alla seguente entità:

users/marie

Utilizza i caratteri jolly, * o **, per rispondere ai cambiamenti nelle entità che corrispondono a un pattern. Il carattere jolly * corrisponde a un singolo segmento e il carattere jolly a più segmenti ** corrisponde a zero o più segmenti nel pattern.

Per le corrispondenze di singoli segmenti (*), puoi anche utilizzare un gruppo di acquisizione denominato, ad esempio users/{userId}.

La seguente tabella mostra pattern di percorso validi:

Pattern Descrizione
users/* o users/{userId} Corrisponde a tutte le entità di tipo users. Non corrisponde al livello delle entità discendenti come /users/marie/messages/33e2IxYBD9enzS50SJ68
users/** Corrisponde a tutte le entità di tipo users e a tutte le entità discendenti come /users/marie/messages/33e2IxYBD9enzS50SJ68

Per scoprire di più sui pattern di percorso, consulta Pattern di percorso Eventarc.

Il trigger deve sempre puntare a un'entità, anche se utilizzi un carattere jolly. Vedi i seguenti esempi:

  • users/{userId=*}/{messages=*} non è valido perché {messages=*} è un ID tipo.

  • users/{userId=*}/{messages}/{messageId=*} è valido perché {messageId=*} punta sempre a un'entità.

Sequenza di caratteri di escape

La sezione descrive le situazioni in cui è necessario eseguire l'interpretazione letterale dei caratteri negli ID tipo e negli ID entità. L'interpretazione letterale di un carattere consente al filtro eventi di interpretare correttamente l'ID.

  • Se un ID tipo o un ID entità include un carattere ~ o /, devi utilizzare il carattere di escape per l'ID nel filtro eventi. Per eseguire l'escape di un ID, utilizza il formato __escENCODED_ID__. Sostituisci ENCODED_ID con un ID tipo o un ID entità in cui tutti i caratteri ~ e / sono sostituiti dai rispettivi ID codifica, che sono i seguenti:

    • ~: ~0
    • /: ~1

    Ad esempio, l'ID tipo user/profile diventa __escusers~1profile__. Un esempio di pattern di percorso con questo ID tipo è __escusers~1profile__/{userId}

  • Se utilizzi l'ID tipo o l'ID entità di . o .. nel filtro eventi, devi eseguire il escape dell'ID come segue:

    • .: __esc~2__
    • ..: __esc~2~2__

    Il carattere . deve essere preceduto da caratteri di escape solo se l'ID è esattamente . o ... Ad esempio, l'ID tipo customers.info non richiede caratteri di escape.

  • Se il tipo o l'ID entità è un valore numerico anziché un valore stringa, devi inserire __idNUMERIC_VALUE__ in caratteri escape. Ad esempio, il pattern del percorso per un'entità di tipo 111 e ID entità 222 è __id111__/__id222__.

  • Se hai eseguito la migrazione da Cloud Datastore legacy a Firestore in modalità Datastore, il database potrebbe contenere ID legacy con una codifica non UTF8. Questi ID devono essere preceduti dal carattere di escape __bytesBASE64_ENCODING__. Sostituisci BASE64_ENCODING con la codifica Base64 dell'ID. Ad esempio, il pattern del percorso Task/{task} con caratteri di escape per l'ID di tipo non UTF8 Task diventa __bytesVGFzaw==__/{task}.

Funzioni di esempio

L'esempio seguente mostra come ricevere gli eventi in modalità Datastore. Per lavorare con i dati coinvolti in un evento, controlla i campi value e old_value.

  • value: un oggetto EntityResult che contiene uno snapshot dell'entità post-operazione. Questo campo non viene compilato per gli eventi di eliminazione.
  • old_value: un oggetto EntityResult che contiene uno snapshot dell'entità pre-operazione. Questo campo viene compilato solo per gli eventi di aggiornamento ed eliminazione.

Java

Per informazioni su come installare e utilizzare la libreria client per la modalità Datastore, consulta Librerie client in modalità Datastore. Per maggiori informazioni, consulta la documentazione di riferimento dell'API Java per la modalità Datastore.

Per eseguire l'autenticazione in modalità Datastore, configura le Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.

import com.google.cloud.functions.CloudEventsFunction;
import com.google.events.cloud.datastore.v1.EntityEventData;
import com.google.protobuf.InvalidProtocolBufferException;
import io.cloudevents.CloudEvent;
import java.util.logging.Logger;

public class Datastore implements CloudEventsFunction {
  private static final Logger logger = Logger.getLogger(Datastore.class.getName());

  @Override
  public void accept(CloudEvent event) throws InvalidProtocolBufferException {
    EntityEventData datastoreEventData = EntityEventData.parseFrom(event.getData().toBytes());

    logger.info("Function triggered by event on: " + event.getSource());
    logger.info("Event type: " + event.getType());

    logger.info("Old value:");
    logger.info(datastoreEventData.getOldValue().toString());

    logger.info("New value:");
    logger.info(datastoreEventData.getValue().toString());
  }
}

Includi le dipendenze proto nell'origine

Devi includere il file in modalità Datastore data.proto nella directory di origine per la funzione. Questo file importa i seguenti proto, che devi includere anche nella directory di origine:

Usa la stessa struttura di directory per le dipendenze. Ad esempio, inserisci struct.proto in google/protobuf.

Questi file sono necessari per decodificare i dati sugli eventi. Se l'origine della funzione non include questi file, restituisce un errore durante l'esecuzione.

Attributi evento

Ogni evento include attributi dei dati che includono informazioni sull'evento, come l'ora in cui l'evento è stato attivato. Firestore in modalità Datastore aggiunge ulteriori dati sul database e sull'entità coinvolta nell'evento. Puoi accedere a questi attributi nel seguente modo:

Java
logger.info("Event time " + event.getTime());
logger.info("Event project: " + event.getExtension("project"));
logger.info("Event location: " + event.getExtension("location"));
logger.info("Database name: " + event.getExtension("database"));
logger.info("Database namespace: " + event.getExtension("namespace"));
logger.info("Database entity: " + event.getExtension("entity"));
// For withAuthContext events
logger.info("Auth information: " + event.getExtension("authid"));
logger.info("Auth information: " + event.getExtension("authtype"));

Esegui il deployment di una funzione

Gli utenti che eseguono il deployment di Cloud Functions devono avere il ruolo IAM Sviluppatore Cloud Functions o un ruolo che includa le stesse autorizzazioni. Vedi anche Configurazione aggiuntiva per il deployment.

Puoi eseguire il deployment di una funzione usando gcloud CLI o la console Google Cloud. L'esempio seguente mostra il deployment con gcloud CLI. Per maggiori dettagli sul deployment con la console Google Cloud, consulta Eseguire il deployment di Cloud Functions.

  1. Nella console Google Cloud, attiva Cloud Shell.

    Attiva Cloud Shell

    Nella parte inferiore della console Google Cloud viene avviata una sessione di Cloud Shell che mostra un prompt della riga di comando. Cloud Shell è un ambiente shell con Google Cloud CLI già installato e con valori già impostati per il progetto attuale. L'inizializzazione della sessione può richiedere alcuni secondi.

  2. Utilizza il comando gcloud functions deploy per eseguire il deployment di una funzione:

    gcloud functions deploy FUNCTION_NAME \
    --gen2 \
    --region=FUNCTION_LOCATION \
    --trigger-location=TRIGGER_LOCATION \
    --runtime=RUNTIME \
    --source=SOURCE_LOCATION \
    --entry-point=CODE_ENTRYPOINT \
    --trigger-event-filters="type=EVENT_FILTER_TYPE" \
    --trigger-event-filters="database=DATABASE" \
    --trigger-event-filters="namespace=NAMESPACE" \
    --trigger-event-filters-path-pattern="entity=ENTITY_OR_PATH" \
    

    Il primo argomento, FUNCTION_NAME, è un nome della funzione di cui hai eseguito il deployment. Il nome della funzione deve iniziare con una lettera seguita da un massimo di 62 lettere, numeri, trattini o trattini bassi e deve terminare con una lettera o un numero. Sostituisci FUNCTION_NAME con un nome di funzione valido. Quindi, aggiungi i seguenti flag:

    • Il flag --gen2 specifica che vuoi eseguire il deployment su Cloud Functions (2nd gen). L'omissione di questo flag comporta il deployment in Cloud Functions (1ª generazione.).

    • Il flag --region=FUNCTION_LOCATION specifica la regione in cui eseguire il deployment della funzione.

      Per massimizzare la prossimità, imposta FUNCTION_LOCATION su una regione vicina al tuo database Firestore. Se il tuo database Firestore si trova in una località multiregionale, imposta il valore su us-central1 per i database in nam5 e su europe-west4 per i database in eur3. Per le località di Firestore a livello di regione, imposta la stessa regione.

    • Il flag --trigger-location=TRIGGER_LOCATION specifica la posizione dell'attivatore. Devi impostare TRIGGER_LOCATION sulla località del database in modalità Datastore.

    • Il flag --runtime=RUNTIME specifica il runtime del linguaggio utilizzato dalla funzione. Cloud Functions supporta diversi runtime. Per ulteriori informazioni, consulta Runtime. Imposta RUNTIME su un runtime supportato.

    • Il flag --source=SOURCE_LOCATION specifica la posizione del codice sorgente della funzione. Per informazioni dettagliate, consulta quanto segue:

      Imposta SOURCE_LOCATION nella posizione del codice sorgente della funzione.

    • Il flag --entry-point=CODE_ENTRYPOINT specifica il punto di ingresso della funzione nel codice sorgente. Si tratta del codice che la funzione esegue quando viene eseguita. Devi impostare CODE_ENTRYPOINT su un nome di funzione o su un nome completo di classe esistente nel codice sorgente. Per ulteriori informazioni, consulta Punto di ingresso alla funzione.

    • I flag --trigger-event-filters definiscono il filtro eventi che include il tipo di trigger e l'entità o il percorso che attiva gli eventi. Imposta i seguenti valori degli attributi per definire il filtro eventi:

      • type=EVENT_FILTER_TYPE: Firestore supporta i seguenti tipi di eventi:

        • google.cloud.datastore.entity.v1.created: l'evento viene inviato quando un'entità viene scritta per la prima volta.
        • google.cloud.datastore.entity.v1.updated: l'evento viene inviato quando un'entità esiste già e ha un valore modificato.
        • google.cloud.datastore.entity.v1.deleted: l'evento viene inviato quando un'entità viene eliminata.
        • google.cloud.datastore.entity.v1.written: l'evento viene inviato quando un'entità viene creata, aggiornata o eliminata.
        • google.cloud.datastore.entity.v1.created.withAuthContext: l'evento viene inviato quando un documento viene scritto per la prima volta e include informazioni di autenticazione aggiuntive.
        • google.cloud.datastore.entity.v1.updated.withAuthContext: l'evento viene inviato quando un documento esiste già e ha un valore modificato. Include informazioni di autenticazione aggiuntive
        • google.cloud.datastore.entity.v1.deleted.withAuthContext: l'evento viene inviato quando un documento viene eliminato. Include informazioni di autenticazione aggiuntive
        • google.cloud.datastore.entity.v1.written.withAuthContext: l'evento viene inviato quando un documento viene creato, aggiornato o eliminato. Include informazioni di autenticazione aggiuntive

        Imposta EVENT_FILTER_TYPE su uno di questi tipi di eventi.

      • database=DATABASE: il database Firestore. Per il nome predefinito del database, imposta DATABASE su (default).

      • namespace=NAMESPACE: lo spazio dei nomi del database. Per il nome del database predefinito, imposta NAMESPACE su (default). Rimuovi il flag in modo che corrisponda a qualsiasi spazio dei nomi.

      • entity=ENTITY_OR_PATH: il percorso del database che attiva gli eventi quando i dati vengono creati, aggiornati o eliminati. I valori accettati per ENTITY_OR_PATH sono:

        • Uguale; ad esempio, --trigger-event-filters="entity='users/marie'"
        • Pattern del percorso, ad esempio --trigger-event-filters-path-pattern="entity='users/*'". Per saperne di più, consulta Comprendere i pattern dei percorsi.

      Facoltativamente, puoi specificare ulteriori opzioni di configurazione, networking e sicurezza quando esegui il deployment di una funzione.

      Per un riferimento completo sul comando deployment e sui suoi flag, consulta la documentazione di gcloud functions deploy.

Deployment di esempio

I seguenti esempi dimostrano i deployment con Google Cloud CLI.

Esegui il deployment di una funzione per un database nella regione us-west2:

gcloud functions deploy gcfv2-trigger-datastore-node \
--gen2 \
--region=us-west2 \
--trigger-location=us-west2 \
--runtime=nodejs18 \
--source=gs://example_bucket-1/datastoreEventFunction.zip \
--entry-point=makeUpperCase \
--trigger-event-filters=type=google.cloud.datastore.entity.v1.written \
--trigger-event-filters=database='(default)' \
--trigger-event-filters-path-pattern="entity='messages/{pushId}'"

Esegui il deployment di una funzione per un database nella località multiregionale nam5:

gcloud functions deploy gcfv2-trigger-datastore-python \
--gen2 \
--region=us-central1 \
--trigger-location=nam5 \
--runtime=python311 \
--source=gs://example_bucket-1/datastoreEventFunction.zip \
--entry-point=make_upper_case \
--trigger-event-filters=type=google.cloud.datastore.entity.v1.written.withAuthContext \
--trigger-event-filters=database='(default)' \
--trigger-event-filters-path-pattern="entity='messages/{pushId}'"

Limitazioni

Tieni presente le seguenti limitazioni per i trigger Firestore per Cloud Functions:

  • Cloud Functions (1ª generazione.) prepara un database "(predefinito)" esistente in modalità nativa Firestore. Non supporta i database denominati Firestore o la modalità Datastore. In questi casi, usa Cloud Functions (2ª generazione.) per configurare gli eventi.
  • L'ordine non è garantito. Modifiche rapide possono attivare chiamate di funzione in un ordine inaspettato.
  • Gli eventi vengono pubblicati almeno una volta, ma un singolo evento può generare più chiamate di funzione. Evita di dipendere dalla meccanica "exactly-once" e scrivi funzioni idempotenti.
  • Firestore in modalità Datastore richiede Cloud Functions (2nd gen). Cloud Functions (1ª generazione.) non supporta la modalità Datastore.
  • Un trigger è associato a un singolo database. Non puoi creare un trigger che corrisponde a più database.
  • L'eliminazione di un database non elimina automaticamente alcun trigger per quel database. L'attivatore interrompe la pubblicazione degli eventi, ma continua a esistere finché non elimini l'attivatore.
  • Se un evento corrispondente supera le dimensioni massime della richiesta, l'evento potrebbe non essere pubblicato in Cloud Functions (1ª generazione.).
    • Gli eventi non consegnati a causa delle dimensioni della richiesta vengono registrati nei log della piattaforma e conteggiati ai fini dell'utilizzo dei log per il progetto.
    • Puoi trovare questi log in Esplora log con il messaggio "Impossibile consegnare l'evento alla funzione Cloud Functions a causa del superamento del limite per la 1ª generazione..." con gravità error. Puoi trovare il nome della funzione sotto il campo functionName. Se il campo receiveTimestamp è ancora a un'ora da questo momento, puoi dedurre i contenuti effettivi dell'evento leggendo il documento in questione con uno snapshot prima e dopo il timestamp.
    • Per evitare questa frequenza, puoi:
      • Esegui la migrazione e l'upgrade a Cloud Functions (2nd gen)
      • Ridimensiona il documento
      • Elimina le funzioni Cloud Functions in questione
    • Puoi disattivare il logging utilizzando le esclusioni, ma tieni presente che gli eventi offensivi non verranno comunque recapitati.

Eventarc e Firestore in località in modalità Datastore

Eventarc non supporta regioni multiple per i trigger di eventi Firestore, ma puoi comunque creare trigger per i database Firestore in località multiregionali. Eventarc mappa le località di Firestore con più regioni alle seguenti regioni Eventarc:

Firestore (più regioni) Regione Eventarc
nam5 us-central1
eur3 europe-west4

Passaggi successivi