Расширьте Data Connect с помощью облачных функций

С помощью Cloud Functions for Firebase вы можете обрабатывать события в Firebase Data Connect . Cloud Functions позволяет запускать серверный код в ответ на события, например, выполнение мутации в службе Data Connect . Это позволяет добавлять пользовательскую логику без развертывания собственных серверов.

Распространенные варианты использования

  • Синхронизация данных: репликация или синхронизация данных с другими системами (например, Cloud Firestore , BigQuery или внешними API) после возникновения мутации.

  • Асинхронные рабочие процессы: запускайте длительные процессы, такие как обработка изображений или агрегация данных, после изменения базы данных.

  • Взаимодействие с пользователями: отправляйте пользователям электронные письма или уведомления Cloud Messaging после определенного события мутации в вашем приложении, например создания учетной записи.

Запустить функцию при мутации Data Connect

Вы можете активировать функцию при каждом выполнении мутации Data Connect , используя обработчик событий onMutationExecuted . Этот триггер срабатывает при выполнении мутации .

Базовая функция события мутации

Следующий простой пример представляет собой функцию, которая регистрирует сведения о любой мутации, выполненной в вашей службе Data 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,
    });
  }
);

Питон

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)

При запуске всех мутаций в проекте не следует выполнять никаких мутаций в обработчике триггера, иначе возникнет бесконечный цикл. Если вы хотите выполнить мутации в триггере события, используйте описанные ниже параметры фильтрации и следите за тем, чтобы мутация не запускалась сама по себе.

Установите местоположение функции

Чтобы события вызывали функцию, её местоположение должно совпадать с местоположением службы Data Connect . По умолчанию областью действия функции является us-central1 .

Node.js

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

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

Питон

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

Фильтр событий

Обработчик onMutationExecuted можно настроить с помощью параметров фильтрации событий по определённым атрибутам. Это полезно, если вы хотите, чтобы функция запускалась только при определённых мутациях.

Вы можете фильтровать по service , connector и 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.
  }
);

Питон

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)

Универсальные символы и группы захвата

Вы можете использовать подстановочные знаки и группы захвата для фильтрации триггеров по нескольким значениям. Все захваченные группы доступны для использования в event.params . Подробнее см. в разделе «Понимание шаблонов пути» .

Примеры:

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.
  }
);

Питон

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

Доступ к информации об аутентификации пользователя

Вы можете получить доступ к информации об аутентификации пользователя, инициировавшего событие. Подробнее о данных, доступных в контексте аутентификации, см. в разделе Контекст аутентификации .

В следующем примере показано, как получить информацию аутентификации:

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
  }
);

Питон

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

Тип аутентификации и идентификатор аутентификации будут заполнены следующим образом:

Мутация, инициированная тип авторизации аутид
Аутентифицированный конечный пользователь app_user UID токена аутентификации Firebase
Неаутентифицированный конечный пользователь unauthenticated пустой
Admin SDK, выдающий себя за конечного пользователя app_user UID токена аутентификации Firebase для выдаваемого пользователя
Admin SDK имитирует неаутентифицированный запрос unauthenticated пустой
Admin SDK с полными правами admin пустой

Доступ к данным о событиях

Объект CloudEvent , переданный вашей функции, содержит информацию о событии, которое его вызвало.

Атрибуты событий

Атрибут Тип Описание
id string Уникальный идентификатор события.
source string Ресурс коннектора, который создал событие (например, //firebasedataconnect.googleapis.com/projects/*/locations/*/services/*/connectors/* ).
specversion string Версия спецификации CloudEvents (например, «1.0»).
type string Тип события: google.firebase.dataconnect.connector.v1.mutationExecuted .
time string Метка времени (формат ISO 8601), указывающая на момент создания события.
subject string Необязательно. Дополнительная информация о контексте события, например, название операции.
params object Карта зафиксированных маршрутов.
authType string Перечисление, представляющее тип принципала, вызвавшего событие.
authId string Уникальный идентификатор принципала, инициировавшего событие.
data MutationEventData Полезная нагрузка события Data Connect . См. следующий раздел.

Полезная нагрузка данных

Объект MutationEventData содержит полезную нагрузку события Data 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 : объект, содержащий переменные, которые были переданы мутации.
  • payload.data : объект, содержащий данные, возвращенные мутацией.
  • payload.errors : Массив ошибок, возникших во время выполнения мутации. Если мутация прошла успешно, этот массив будет пустым.

Пример

Вот как можно получить доступ к переменным мутации и возвращаемым данным:

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
  }
);

Питон

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

Обратите внимание, что в отличие от некоторых других триггеров баз данных, таких как Cloud Firestore или Realtime Database , событие Data Connect не предоставляет снимок данных «до». Поскольку Data Connect передаёт запросы к базовой базе данных, снимок данных «до» невозможно получить транзакционно. Вместо этого вы получаете доступ к аргументам, переданным мутации, и к данным, которые она вернула.

Одним из следствий этого является невозможность использовать стратегию сравнения снимков «до» и «после» для предотвращения бесконечных циклов, в которых событие-триггер запускает одно и то же событие. Если необходимо выполнить мутацию из функции, вызванной событием мутации, используйте фильтры событий и позаботьтесь о том, чтобы никакая мутация не могла запустить себя сама, даже косвенно.