使用 Cloud Functions for Firebase,您可以处理 Firebase Data Connect 中的事件。Cloud Functions 允许您运行服务器端代码以响应事件,例如在您的 Data Connect 服务中执行 mutation。这样一来,您无需部署自己的服务器即可添加自定义逻辑。
常见使用场景
数据同步:在发生变更后,将数据复制或同步到其他系统(如Cloud Firestore、BigQuery 或外部 API)。
异步工作流:在数据库更改后启动长时间运行的进程,例如图像处理或数据聚合。
用户互动: 在您的应用程序中发生特定变更事件(例如创建账号)后,向用户发送电子邮件或Cloud Messaging通知。
在 Data Connect 突变时触发函数
您可以使用 onMutationExecuted 事件处理程序在执行 Data Connect 变更时触发一个函数。此触发器在执行 mutation 时发生。
基本突变事件函数
以下基本示例是一个函数,用于记录在您的 Data Connect 服务中执行的任何 mutation 的详细信息:
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
身份验证类型和身份验证 ID 将按如下方式填充:
| 突变由发起 | authtype | authid |
|---|---|---|
| 已认证的最终用户 | app_user |
Firebase Auth 令牌 UID |
| 未经身份验证的最终用户 | unauthenticated |
空白 |
| Admin SDK 模拟最终用户 | app_user
|
被模拟用户的 Firebase Auth 令牌 UID |
| Admin 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: 包含传递给 mutation 的变量的对象。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 代理对底层数据库的请求,所以无法通过事务获取数据的“之前”快照。相反,您可以访问传递给 mutation 的参数以及它返回的数据。
由此产生的一个后果是,你不能使用比较“之前”和“之后”快照的策略来避免无限循环,在无限循环中,一个事件触发器会触发同一个事件。如果必须从由突变事件触发的函数中执行突变,请使用事件过滤器,并注意确保任何突变都不会触发自身,即使是间接触发。