Расширьте 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,
    });
  }
);

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)

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

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

Для запуска функции событиями местоположение функции должно совпадать с местоположением службы 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) => { /* ... */ }
);

Python

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

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)

Подстановочные символы и группы захвата

Вы можете использовать подстановочные знаки и группы захвата для фильтрации триггеров по нескольким значениям. Все захваченные группы доступны для использования в 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.
  }
);

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

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

Вы можете получить доступ к информации об аутентификации пользователя, который инициировал событие. Дополнительную информацию о данных, доступных в контексте аутентификации, см. в разделе «Контекст аутентификации» .

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

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

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

Мутация, инициированная authtype аутид
Аутентифицированный конечный пользователь app_user UID токена аутентификации Firebase
Неаутентифицированный конечный пользователь unauthenticated пустой
Admin SDK имитирует действия конечного пользователя. app_user UID токена аутентификации Firebase для пользователя, от имени которого осуществляется операция аутентификации.
Административный SDK имитирует неаутентифицированный запрос. unauthenticated пустой
Административный 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
  }
);

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

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

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