באמצעות Cloud Functions for Firebase, אפשר לנהל אירועים בFirebase Data Connect. Cloud Functions מאפשר להריץ קוד מצד השרת בתגובה לאירועים, כמו הפעלה של מוטציה בשירות Data Connect. כך תוכלו להוסיף לוגיקה מותאמת אישית בלי לפרוס שרתים משלכם.
תרחישים נפוצים לדוגמה
סנכרון נתונים: שכפול או סנכרון של נתונים עם מערכות אחרות (כמו Cloud Firestore, BigQuery או ממשקי API חיצוניים) אחרי שמתרחש שינוי.
תהליכי עבודה אסינכרוניים: אפשר להפעיל תהליכים ארוכים, כמו עיבוד תמונות או צבירת נתונים, אחרי שינוי במסד הנתונים.
מעורבות משתמשים: שליחת אימיילים או הודעות Cloud Messaging למשתמשים אחרי אירוע מוטציה ספציפי באפליקציה, כמו יצירת חשבון.
הפעלת פונקציה ב-Data Connect mutation
אתם יכולים להפעיל פונקציה בכל פעם שמתבצעת Data Connect מוטציה
באמצעות onMutationExecuted event handler. הטריגר הזה מופעל כשמבצעים מוטציה.
פונקציית אירוע Mutation בסיסית
הדוגמה הבסיסית הבאה היא פונקציה שמתעדת את הפרטים של כל מוטציה שמופעלת בשירות 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)
כשמפעילים את הטריגר על כל השינויים בפרויקט, אסור לבצע שינויים ב-trigger handler, אחרת תיווצר לולאה אינסופית. אם רוצים לבצע מוטציות בטריגר של אירוע, צריך להשתמש באפשרויות הסינון שמתוארות בהמשך, ולוודא שהמוטציה לא מפעילה את עצמה.
הגדרת המיקום של הפונקציה
מיקום הפונקציה צריך להיות זהה למיקום השירות 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
סינון אירועים
אפשר להגדיר את ה-handler 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 | authid |
|---|---|---|
| משתמש קצה מאומת | app_user |
מזהה משתמש (UID) של טוקן אימות ב-Firebase |
| משתמש קצה לא מאומת | unauthenticated |
ריק |
| Admin SDK מתחזה למשתמש קצה | app_user
|
מזהה המשתמש (UID) של האסימון של Firebase Auth של המשתמש שהוגדר כמשתמש שמבצע פעולות בשם משתמש אחר |
| 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 |
סוג של enum שמייצג את סוג הגורם שהפעיל את האירוע. |
authId |
string |
מזהה ייחודי של הגורם הראשי שהפעיל את האירוע. |
data |
MutationEventData |
המטען הייעודי של אירוע Data Connect. מידע נוסף מופיע בקטע הבא. |
מטען ייעודי (payload) של נתונים
האובייקט MutationEventData מכיל את המטען הייעודי (Payload) של האירוע 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 מעביר בקשות למסד הנתונים הבסיסי, אי אפשר לקבל את תמונת המצב של הנתונים לפני העיבוד באופן טרנזקציונלי. במקום זאת, יש לכם גישה לארגומנטים שנשלחו למוטציה ולנתונים שהוחזרו ממנה.
אחת מההשלכות של זה היא שאי אפשר להשתמש באסטרטגיה של השוואת תמונות מצב 'לפני' ו'אחרי' כדי למנוע לולאות אינסופיות, שבהן טריגר של אירוע מפעיל את אותו אירוע. אם אתם חייבים לבצע מוטציה מפונקציה שהופעלה על ידי אירוע מוטציה, השתמשו במסנני אירועים והקפידו לוודא שאף מוטציה לא יכולה להפעיל את עצמה, גם לא באופן עקיף.