Rozszerzanie SQL Connect za pomocą Cloud Functions

Dzięki Cloud Functions for Firebase możesz obsługiwać zdarzenia w Firebase SQL Connect. Cloud Functions umożliwia uruchamianie kodu po stronie serwera w odpowiedzi na zdarzenia, takie jak wykonanie mutacji w usłudze SQL Connect. Dzięki temu możesz dodawać niestandardową logikę bez wdrażania własnych serwerów.

Częste przypadki użycia

  • Synchronizacja danych: replikowanie lub synchronizowanie danych z innymi systemami (takimi jak Cloud Firestore, BigQuery lub zewnętrzne interfejsy API) po wystąpieniu mutacji.

  • Asynchroniczne przepływy pracy: uruchamiaj długotrwałe procesy, takie jak przetwarzanie obrazów lub agregacja danych, po zmianie bazy danych.

  • Zaangażowanie użytkowników: wysyłaj e-maile lub powiadomienia Cloud Messaging do użytkowników po określonym zdarzeniu mutacji w aplikacji, takim jak utworzenie konta.

Aktywowanie funkcji przy mutacji SQL Connect

Możesz aktywować funkcję za każdym razem, gdy wykonywana jest mutacja SQL Connect, używając modułu obsługi zdarzeń onMutationExecuted. Ten aktywator jest uruchamiany po wykonaniu mutacji.

Podstawowa funkcja zdarzenia mutacji

Poniższy podstawowy przykład to funkcja, która rejestruje szczegóły każdej mutacji wykonanej w usłudze SQL Connect:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

export const logMutation = onMutationExecuted(
  {
    /* Trigger on all mutations, spanning all services and connectors
       in us-central1 */
  },
  (event) => {
    logger.info("A mutation was executed!", {
      data: event.data,
    });
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed()
def log_mutation(event: dataconnect_fn.Event):
  logger.info("A mutation was executed!", event.data)

Jeśli wyzwalacz jest aktywowany przez wszystkie mutacje w projekcie, nie możesz wykonywać żadnych mutacji w module obsługi wyzwalacza, ponieważ spowoduje to nieskończoną pętlę. Jeśli chcesz przeprowadzać mutacje w aktywatorze zdarzenia, użyj opisanych poniżej opcji filtrowania i upewnij się, że mutacja nie wywołuje samej siebie.

Ustawianie lokalizacji funkcji

Aby zdarzenia mogły aktywować funkcję, lokalizacja funkcji musi być zgodna z lokalizacją usługi SQL Connect. Domyślny region funkcji to us-central1.

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

export const onMutationRegionOption = onMutationExecuted(
  {
    region: "europe-west1"  // Set if SQL Connect service location is not us-central1
  },
  (event) => { /* ... */ }
);

Python

@dataconnect_fn.on_mutation_executed(
  region="europe-west1"  # Set if SQL Connect service location is not us-central1
)
def mutation_executed_handler_region_option(event: dataconnect_fn.Event):
  pass

Filtruj zdarzenia

Moduł obsługi onMutationExecuted można skonfigurować za pomocą opcji filtrowania zdarzeń na podstawie określonych atrybutów. Jest to przydatne, gdy chcesz aktywować funkcję tylko w przypadku określonych mutacji.

Możesz filtrować według service, connector i operation:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

// Trigger this function only for the CreateUser mutation
// in the users connector of the myAppService service.
export const onUserCreate = onMutationExecuted(
  {
    service: "myAppService",
    connector: "users",
    operation: "CreateUser",
  },
  (event) => {
    logger.info("A new user was created!", event.data);
    // Add logic here: for example, sending a welcome email.
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  connector="users",
  operation="CreateUser"
):
def on_user_create(event: dataconnect_fn.Event):
  logger.info("A new user was created!", event.data)

Symbole wieloznaczne i grupy przechwytywania

Możesz używać symboli wieloznacznych i grup przechwytywania, aby filtrować reguły według wielu wartości. Wszystkie zarejestrowane grupy są dostępne w aplikacji event.params. Więcej informacji znajdziesz w artykule Wzorce ścieżek.

Przykłady:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

// Trigger on all operations that match the pattern `User*`, on any service and
// connector.
export const onMutationWildcards = onMutationExecuted(
  {
    operation: "User*",
  },
  (event) => {}
);

// Trigger on all operations that match the pattern `User*`, on any service and
// connector. Capture the operation name in the variable `op`.
export const onMutationCaptureWildcards = onMutationExecuted(
  {
    operation: "{op=User*}",
  },
  (event) => {
    // `event.params.op` contains the operation name.
  }
);

// Trigger on all operations on the service `myAppService`. Capture the
// operation name in the variable `operation`.
export const onMutationCaptures = onMutationExecuted(
  {
    service: "myAppService",
    operation: "{operation}",
  },
  (event) => {
    // `event.params.operation` contains the operation name.
  }
);

Python

from firebase_functions import dataconnect_fn

# Trigger on all operations that match the pattern `User*`, on any service and
# connector.
@dataconnect_fn.on_mutation_executed(
  operation="User*"
)
def on_mutation_wildcards(event: dataconnect_fn.Event):
  pass

# Trigger on all operations that match the pattern `User*`, on any service and
# connector. Capture the operation name in the variable `op`.
@dataconnect_fn.on_mutation_executed(
  operation="{op=User*}"
)
def on_mutation_capture_wildcards(event: dataconnect_fn.Event):
  # `event.params["op"]` contains the operation name.
  pass

# Trigger on all operations on the service `myAppService`. Capture the
# operation name in the variable `operation`.
@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  operation="{operation}"
)
def on_mutation_captures(event: dataconnect_fn.Event):
  # `event.params["operation"]` contains the operation name.
  pass

Uzyskiwanie dostępu do informacji o uwierzytelnianiu użytkowników

Możesz uzyskać dostęp do informacji o uwierzytelnianiu użytkownika, który wywołał zdarzenie. Więcej informacji o danych dostępnych w kontekście uwierzytelniania znajdziesz w artykule Kontekst uwierzytelniania.

Poniższy przykład pokazuje, jak pobrać informacje uwierzytelniające:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";

export const onMutation = onMutationExecuted(
  { operation: "MyMutation" },
  (event) => {
    // mutationExecuted event provides authType and authId:
    // event.authType
    // event.authId
  }
);

Python

from firebase_functions import dataconnect_fn

@dataconnect_fn.on_mutation_executed(operation="MyMutation")
def mutation_executed_handler(event: dataconnect_fn.Event):
  # mutationExecuted event provides auth_type and auth_id, which are accessed as follows
  # event.auth_type
  # event.auth_id
  pass

Typ i identyfikator uwierzytelniania zostaną wypełnione w następujący sposób:

Mutacja zainicjowana przez authtype authid
Uwierzytelniony użytkownik app_user Identyfikator UID tokena Firebase Auth
Nieuwierzytelniony użytkownik unauthenticated puste
Pakiet Admin SDK podszywający się pod użytkownika app_user Identyfikator UID tokena Firebase Auth użytkownika, pod którego się podszywasz.
Pakiet Admin SDK podszywa się pod nieuwierzytelnione żądanie unauthenticated puste
pakiet Admin SDK z pełnymi uprawnieniami admin puste

Uzyskiwanie dostępu do danych zdarzenia

Obiekt CloudEvent przekazany do funkcji zawiera informacje o zdarzeniu, które ją wywołało.

Atrybuty zdarzeń

Atrybut Typ Opis
id string Unikalny identyfikator zdarzenia.
source string Zasób oprogramowania sprzęgającego, który wygenerował zdarzenie (np. //firebasedataconnect.googleapis.com/projects/*/locations/*/services/*/connectors/*).
specversion string Wersja specyfikacji CloudEvents (np. „1.0”).
type string Typ zdarzenia: google.firebase.dataconnect.connector.v1.mutationExecuted.
time string Sygnatura czasowa (w formacie ISO 8601) określająca, kiedy zdarzenie zostało wygenerowane.
subject string Opcjonalnie. Dodatkowe informacje o kontekście zdarzenia, takie jak nazwa operacji.
params object Mapa wzorców przechwyconych ścieżek.
authType string Typ wyliczeniowy reprezentujący typ podmiotu zabezpieczeń, który wywołał zdarzenie.
authId string Unikalny identyfikator podmiotu zabezpieczeń, który wywołał zdarzenie.
data MutationEventData Ładunek zdarzenia SQL Connect. Zobacz następną sekcję.

Ładunek danych

Obiekt MutationEventData zawiera ładunek zdarzenia SQL Connect:

{
  // ...
  "authType": // ...
  "data": {
    "payload": {
      "variables": {
        "userId": "user123",
        "updateData": {
          "displayName": "New Name"
        }
      },
      "data": {
        "updateUser": {
          "id": "user123",
          "displayName": "New Name",
          "email": "user@example.com"
        }
      },
      "errors": []
    }
  }
}
  • payload.variables: obiekt zawierający zmienne przekazane do mutacji.
  • payload.data: obiekt zawierający dane zwrócone przez mutację.
  • payload.errors: tablica błędów, które wystąpiły podczas wykonywania mutacji. Jeśli mutacja się powiedzie, ta tablica będzie pusta.

Przykład

Aby uzyskać dostęp do zmiennych mutacji i zwróconych danych:

Node.js

import { onMutationExecuted } from "firebase-functions/dataconnect";
import { logger } from "firebase-functions";

export const processNewUserData = onMutationExecuted(
  {
    "service": "myAppService",
    "connector": "users",
    "operation": "CreateUser",
  },
  (event) => {
    // The variables passed to the mutation
    const mutationVariables = event.data.payload.variables;

    // The data returned by the mutation
    const returnedData = event.data.payload.data;

    logger.info("Processing mutation with variables:", mutationVariables);
    logger.info("Mutation returned:", returnedData);

    // ... your custom logic here
  }
);

Python

from firebase_functions import dataconnect_fn, logger

@dataconnect_fn.on_mutation_executed(
  service="myAppService",
  connector="users",
  operation="CreateUser"
):
def process_new_user_data(event: dataconnect_fn.Event):
  # The variables passed to the mutation
  mutation_vars = event.data.payload.variables
  # The data returned by the mutation
  returned_data = event.data.payload.data

  logger.info("Processing mutation with variables:", mutationVariables)
  logger.info("Mutation returned", returnedData)

  # ... your custom logic here

Pamiętaj, że w przeciwieństwie do innych aktywatorów bazy danych, takich jak Cloud Firestore lub Realtime Database, zdarzenie SQL Connect nie udostępnia migawki danych „przed”. Ponieważ SQL Connect przekazuje żądania do bazy danych, nie można uzyskać migawki danych „przed” w sposób transakcyjny. Zamiast tego masz dostęp do argumentów wysłanych do mutacji i zwróconych przez nią danych.

Jedną z konsekwencji jest to, że nie można używać strategii porównywania stanu „przed” i „po”, aby uniknąć nieskończonych pętli, w których reguła zdarzenia wywołuje to samo zdarzenie. Jeśli musisz wykonać mutację z funkcji wywołanej przez zdarzenie mutacji, użyj filtrów zdarzeń i upewnij się, że żadna mutacja nie może wywołać samej siebie, nawet pośrednio.