Estendi Datastore con Cloud Functions (2nd gen)

Con Cloud Functions ed Eventarc, puoi eseguire il deployment del codice per gestire gli eventi attivati da modifiche nel tuo database Firestore in modalità Datastore. Ciò ti consente di aggiungere funzionalità lato server senza eseguire i tuoi server.

Trigger della modalità Datastore

Eventarc supporta i seguenti attivatori 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 Si attiva 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 Si attiva 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 Come created, ma aggiunge informazioni di autenticazione.
google.cloud.datastore.entity.v1.updated.withAuthContext Come updated, ma aggiunge informazioni di autenticazione.
google.cloud.datastore.entity.v1.deleted.withAuthContext Come deleted, ma aggiunge informazioni di autenticazione.
google.cloud.datastore.entity.v1.written.withAuthContext Come written, ma aggiunge informazioni di autenticazione.

I trigger di eventi in modalità Datastore rispondono solo alle modifiche delle entità. Un aggiornamento a un'entità in modalità Datastore in cui i dati non sono stati modificati (scrittura no-op) 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 ulteriori informazioni di autenticazione sull'evento, utilizza un attivatore di evento 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 authcontext per ulteriori informazioni sui valori degli attributi.

Scrivere una funzione attivata da entità

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

  • un tipo di evento di 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 di eventi, puoi specificare una corrispondenza esatta dell'entità o un pattern del percorso. Utilizza un pattern del percorso per associare più entità ai 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 alle modifiche nelle entità che corrispondono a un pattern. Il carattere jolly * corrisponde a un singolo segmento, mentre il carattere jolly a più segmenti ** corrisponde a zero o più segmenti nel pattern.

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

La tabella seguente illustra 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.

L'attivatore deve sempre puntare a un'entità, anche se utilizzi un carattere jolly. Vedi gli esempi che seguono.

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

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

Caratteri di escape

La sezione descrive situazioni che richiedono l'escape dei caratteri negli ID natura e negli ID entità. L'aggiunta di caratteri di escape a un carattere consente al filtro di eventi di interpretare correttamente l'ID.

  • Se un ID tipo o un ID entità include un carattere ~ o /, devi eseguire l'escape dell'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à che abbia tutti i caratteri ~ e / sostituiti dai relativi ID di 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à . o .. nel filtro eventi, devi eseguire l'escape dell'ID nel seguente modo:

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

    Devi eseguire l'escape del carattere . solo se l'ID è esattamente . o ... Ad esempio, l'ID tipo customers.info non richiede l'escape.

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

  • Se hai eseguito la migrazione da Legacy Cloud Datastore a Firestore in modalità Datastore, il database potrebbe contenere ID legacy con una codifica non UTF8. Devi eseguire l'escape di questi ID con __bytesBASE64_ENCODING__. Sostituisci BASE64_ENCODING con la codifica Base-64 dell'ID. Ad esempio, il pattern del percorso Task/{task} con 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, guarda 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 di entità pre-operation. Questo campo viene compilato solo per gli eventi di aggiornamento ed eliminazione.

Java

Per scoprire 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 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 della funzione. Questo file importa i seguenti proto, che devi includere anche nella directory di origine:

Utilizza la stessa struttura di directory per le dipendenze. Ad esempio, posiziona struct.proto all'interno di google/protobuf.

Questi file sono necessari per decodificare i dati sugli eventi. Se l'origine della funzione non include questi file, viene restituito un errore quando viene eseguita.

Attributi evento

Ogni evento include attributi dei dati che includono informazioni sull'evento, come l'ora in cui è stato attivato. Firestore in modalità Datastore aggiunge ulteriori dati sul database e sull'entità interessata 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 utilizzando gcloud CLI o la console Google Cloud. L'esempio seguente illustra 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 per la 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 in Cloud Functions (2nd gen). Se questo flag viene omesso, viene eseguito 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 vicinanza, 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 sedi di Firestore regionali, impostale sulla 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 Tempi di esecuzione. Imposta RUNTIME su un runtime supportato.

    • Il flag --source=SOURCE_LOCATION specifica la posizione del codice sorgente della funzione. Per i dettagli, vedi quanto segue:

      Imposta SOURCE_LOCATION sulla posizione del codice sorgente della funzione.

    • Il flag --entry-point=CODE_ENTRYPOINT specifica il punto di ingresso alla funzione nel codice sorgente. Questo è il codice che la funzione esegue quando viene eseguita. Devi impostare CODE_ENTRYPOINT su un nome di funzione o su un nome di classe completo esistente nel codice sorgente. Per ulteriori informazioni, consulta Punto di ingresso della 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 viene scritto un documento per la prima volta e l'evento include ulteriori informazioni di autenticazione
        • google.cloud.datastore.entity.v1.updated.withAuthContext: l'evento viene inviato quando un documento esiste già e ha un valore modificato. Include ulteriori informazioni di autenticazione
        • google.cloud.datastore.entity.v1.deleted.withAuthContext: l'evento viene inviato quando viene eliminato un documento. Include informazioni di autenticazione aggiuntive
        • google.cloud.datastore.entity.v1.written.withAuthContext: l'evento viene inviato quando un documento viene creato, aggiornato o eliminato e quando si verifica un evento. Include ulteriori informazioni di autenticazione

        Imposta EVENT_FILTER_TYPE su uno di questi tipi di eventi.

      • database=DATABASE: il database Firestore. Per il nome del database predefinito, 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 relativi 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 di Firestore per Cloud Functions:

  • L'ordine non è garantito. Le modifiche rapide possono attivare chiamate di funzioni in modo imprevisto.
  • Gli eventi vengono recapitati almeno una volta, ma un singolo evento potrebbe comportare più chiamate di funzioni. 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.
  • Cloud Functions (1ª generazione.) funziona solo con il database "(default)" e non supporta i database denominati Firestore. Utilizza Cloud Functions (2ª generazione) per configurare gli eventi per i database denominati.
  • Un trigger è associato a un singolo database. Non puoi creare un trigger corrispondente a più database.
  • L'eliminazione di un database non elimina automaticamente i trigger per quel database. L'attivatore smette di pubblicare eventi, ma continua a esistere finché non lo elimini.
  • Se un evento con corrispondenza supera la dimensione massima della richiesta, l'evento potrebbe non essere consegnato a Cloud Functions (1ª generazione).
    • Gli eventi non recapitati a causa delle dimensioni della richiesta vengono registrati nei log della piattaforma e vengono conteggiati ai fini dell'utilizzo dei log per il progetto.
    • Puoi trovare questi log in Esplora log con il messaggio "L'evento non può essere recapitato 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 entro un'ora da adesso, puoi dedurre i contenuti effettivi dell'evento leggendo il documento in questione con un'istantanea prima e dopo il timestamp.
    • Per evitare questo ritmo, puoi:
      • Migrazione a Cloud Functions (2nd gen) ed upgrade
      • Ridimensiona il documento
      • Elimina la funzione Cloud Functions in questione
    • Puoi disattivare il logging stesso utilizzando le esclusioni, ma tieni presente che gli eventi offensivi non verranno comunque pubblicati.

Eventarc e Firestore nelle località in modalità Datastore

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

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

Passaggi successivi