Estendere Datastore con Cloud Functions (2nd gen)

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

Trigger della modalità Datastore

Eventarc supporta i seguenti trigger di eventi Firestore in modalità Datastore per consentirti di creare gestori di funzioni Cloud Run (2ª generazione.) collegati a eventi Firestore 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 Attivato quando un'entità esiste già e un valore è stato modificato.
google.cloud.datastore.entity.v1.deleted Si attiva quando viene eliminata un'entità.
google.cloud.datastore.entity.v1.written Si attiva quando viene attivato created, updated o deleted.
google.cloud.datastore.entity.v1.created.withAuthContext Come created, ma aggiunge le informazioni di autenticazione.
google.cloud.datastore.entity.v1.updated.withAuthContext Come updated, ma aggiunge le informazioni di autenticazione.
google.cloud.datastore.entity.v1.deleted.withAuthContext Come deleted, ma aggiunge le informazioni di autenticazione.
google.cloud.datastore.entity.v1.written.withAuthContext Come written, ma aggiunge le informazioni di autenticazione.

I trigger di eventi in modalità Datastore rispondono solo alle modifiche alle entità. Un aggiornamento a un'entità in modalità Datastore in cui i dati non vengono modificati (un'operazione di 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 trigger evento con l'estensione withAuthContext. Questa estensione aggiunge ulteriori informazioni sull'entità che ha attivato l'evento. Vengono aggiunti gli attributi authtype e authid, oltre alle informazioni restituite nell'evento di base. Per ulteriori informazioni sui valori degli attributi, consulta il riferimento authcontext.

Scrivere una funzione attivata da un'entità

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

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

Filtri degli eventi di trigger

Quando specifichi un filtro eventi, puoi specificare una corrispondenza esatta dell'entità o un pattern di percorso. Utilizza un pattern di percorso per trovare corrispondenze con più entità con i caratteri jolly * o **.

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

users/marie

Utilizza i caratteri jolly, * o **, per rispondere alle modifiche delle entità che corrispondono a un pattern. Il carattere jolly * corrisponde a un singolo segmento, mentre il carattere jolly ** 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 mostra i 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 saperne 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à.

Escape dei caratteri

Questa sezione descrive le situazioni che richiedono di utilizzare l'interpretazione letterale dei caratteri negli ID tipo e negli ID entità. L'escape di un carattere consente al filtro eventi di interpretare correttamente l'ID.

  • Se un ID tipo o 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 ID entità in cui tutti i caratteri ~ e / sono sostituiti dai rispettivi ID codifica, ovvero:

    • ~: ~0
    • /: ~1

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

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

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

    Devi utilizzare il carattere 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é una stringa, devi eseguire l'escape dell'ID con __idNUMERIC_VALUE__. Ad esempio, il pattern del percorso per un'entità di tipo 111 e ID entità 222 è __id111__/__id222__.

  • Se hai eseguito la migrazione da Legacy Cloud Datastore a Firestore in modalità Datastore, il tuo database potrebbe contenere ID legacy in una codifica non UTF-8. Devi utilizzare l'interpretazione letterale di questi ID con __bytesBASE64_ENCODING__. Sostituisci BASE64_ENCODING con la codifica Base64 dell'ID. Ad esempio, il pattern del percorso Task/{task} con escape per l'ID tipo non UTF8 Task diventa __bytesVGFzaw==__/{task}.

Funzioni di esempio

L'esempio seguente mostra come ricevere eventi in modalità Datastore. Per lavorare con i dati coinvolti in un evento, esamina 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 scoprire come installare e utilizzare la libreria client per la modalità Datastore, consulta la sezione Librerie client della modalità Datastore. Per ulteriori informazioni, consulta la documentazione di riferimento dell'API Java in modalità Datastore.

Per eseguire l'autenticazione in modalità Datastore, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, vedi Configura 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 nella sorgente

Devi includere il file Datastore mode 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, inserisci struct.proto all'interno di google/protobuf.

Questi file sono necessari per decodificare i dati degli 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, ad esempio l'ora in cui è 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 delle funzioni Cloud Run devono disporre del ruolo IAM Sviluppatore di funzioni Cloud Run o di 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 mostra il deployment con gcloud CLI. Per informazioni dettagliate sul deployment con la console Google Cloud , consulta Eseguire il deployment di Cloud Run Functions.

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  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 è stato 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 Run Functions (2ª generazione). Se ometti questo flag, il deployment viene eseguito in Cloud Run Functions 1ª generazionen.).

    • 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 località Firestore regionali, imposta la stessa regione.

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

    • Il flag --runtime=RUNTIME specifica il runtime della lingua utilizzato dalla funzione. Cloud Run Functions supporta diversi runtime. Per saperne di più, consulta la sezione Runtime. Imposta RUNTIME su un runtime supportato.

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

      Imposta SOURCE_LOCATION sul percorso del codice sorgente della funzione.

    • Il flag --entry-point=CODE_ENTRYPOINT specifica il punto di ingresso della funzione nel codice sorgente. Questo è il codice che la tua funzione esegue quando viene eseguita. Devi impostare CODE_ENTRYPOINT su un nome di funzione o un nome di classe completo che esiste nel codice sorgente. Per saperne di più, consulta Entry point della funzione.

    • I flag --trigger-event-filters definiscono il filtro degli eventi che include il tipo di attivatore 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 un valore è stato 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 l'evento include informazioni di autenticazione aggiuntive
        • google.cloud.datastore.entity.v1.updated.withAuthContext: event is sent when a document already exists and has any value changed. Include informazioni di autenticazione aggiuntive
        • google.cloud.datastore.entity.v1.deleted.withAuthContext: event is sent when a document is deleted. 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 evento.

      • 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 per trovare corrispondenze con 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 Informazioni sui pattern di percorso.

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

      Per un riferimento completo al comando di deployment e ai relativi flag, consulta la documentazione gcloud functions deploy.

Esempi di deployment

I seguenti esempi mostrano 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 multiregione 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 le funzioni Cloud Run:

  • Le funzioni Cloud Run (1ª generazione.) richiedono un database "(default)" esistente in modalità nativa Firestore. Non supporta i database denominati Firestore o la modalità Datastore. In questi casi, utilizza Cloud Run Functions (2ª generazione) per configurare gli eventi.
  • L'ordinamento non è garantito. Le modifiche rapide possono attivare le chiamate di funzione in un ordine imprevisto.
  • Gli eventi vengono inviati almeno una volta, ma un singolo evento può comportare più chiamate di funzione. Evita di fare affidamento sulla meccanica di esecuzione esattamente una volta e scrivi funzioni idempotenti.
  • Firestore in modalità Datastore richiede le funzioni Cloud Run (2ª generazione). Cloud Run (1ª generazione.) non supporta la modalità Datastore.
  • Un trigger è associato a un singolo database. Non puoi creare un trigger che corrisponda a più database.
  • L'eliminazione di un database non comporta l'eliminazione automatica di eventuali trigger per quel database. Il trigger smette di inviare eventi, ma continua a esistere finché non lo elimini.
  • Se un evento corrispondente supera le dimensioni massime della richiesta, l'evento potrebbe non essere recapitato alle funzioni Cloud Run (1ª generazione.).
    • Gli eventi non recapitati a causa delle dimensioni della richiesta vengono registrati nei log della piattaforma e vengono conteggiati nell'utilizzo dei log per il progetto.
    • Puoi trovare questi log in Esplora log con il messaggio "Event cannot deliver to Cloud function due to size exceeding the limit for1ª generazionen..." (Impossibile recapitare l'evento alla funzione Cloud a causa delle dimensioni che superano il limite per la prima generazione...) di gravità error. Puoi trovare il nome della funzione nel campo functionName. Se il campo receiveTimestamp è ancora entro un'ora da adesso, puoi dedurre il contenuto effettivo dell'evento leggendo il documento in questione con un'istantanea prima e dopo il timestamp.
    • Per evitare questa cadenza, puoi:
      • Eseguire la migrazione e l'upgrade alle funzioni Cloud Run (2ª generazione.)
      • Ridurre le dimensioni del documento
      • Elimina le funzioni Cloud Run in questione
    • Puoi disattivare il logging utilizzando le esclusioni, ma tieni presente che gli eventi incriminati non verranno comunque recapitati.

Località di Eventarc e Firestore in modalità Datastore

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

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

Passaggi successivi