ขยาย SQL Connect ด้วย Cloud Functions

ด้วย Cloud Functions for Firebase คุณสามารถจัดการเหตุการณ์ใน Firebase SQL Connect ได้ Cloud Functions ช่วยให้คุณเรียกใช้โค้ดฝั่งเซิร์ฟเวอร์เพื่อ ตอบสนองต่อเหตุการณ์ต่างๆ เช่น การดำเนินการ Mutation ในบริการ SQL Connect ซึ่งช่วยให้คุณเพิ่มตรรกะที่กำหนดเองได้โดยไม่ต้องติดตั้งใช้งานเซิร์ฟเวอร์ของคุณเอง

กรณีการใช้งานทั่วไป

  • การซิงค์ข้อมูล: ทำซ้ำหรือซิงค์ข้อมูลกับระบบอื่นๆ (เช่น Cloud Firestore, BigQuery หรือ API ภายนอก) หลังจากเกิด Mutation

  • เวิร์กโฟลว์แบบไม่พร้อมกัน: เริ่มกระบวนการที่ใช้เวลานาน เช่น การประมวลผลรูปภาพหรือการรวมข้อมูล หลังจากมีการเปลี่ยนแปลงฐานข้อมูล

  • การมีส่วนร่วมของผู้ใช้: ส่งอีเมลหรือCloud Messagingการแจ้งเตือนไปยัง ผู้ใช้หลังจากเกิดเหตุการณ์ Mutation ที่เฉพาะเจาะจงในแอปพลิเคชัน เช่น การสร้าง บัญชี

ทริกเกอร์ฟังก์ชันเมื่อเกิด SQL Connect

คุณสามารถทริกเกอร์ฟังก์ชันเมื่อใดก็ตามที่มีการดำเนินการ Mutation ของ SQL Connect โดยใช้ตัวแฮนเดิลเหตุการณ์ onMutationExecuted ทริกเกอร์นี้จะเกิดขึ้นเมื่อมีการดำเนินการ Mutation

ฟังก์ชันเหตุการณ์ Mutation พื้นฐาน

ตัวอย่างพื้นฐานต่อไปนี้เป็นฟังก์ชันที่บันทึกรายละเอียดของ Mutation ที่ดำเนินการในบริการ 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)

เมื่อทริกเกอร์จาก Mutation ทั้งหมดในโปรเจ็กต์ คุณต้องไม่ดำเนินการ Mutation ใดๆ ในตัวแฮนเดิลทริกเกอร์ ไม่เช่นนั้นจะทำให้เกิดลูปไม่สิ้นสุด หากต้องการดำเนินการ Mutation ในทริกเกอร์เหตุการณ์ ให้ใช้ตัวเลือกการกรองที่อธิบายไว้ด้านล่าง และระมัดระวังไม่ให้ Mutation ทริกเกอร์ตัวเอง

ตั้งค่าตำแหน่งฟังก์ชัน

ตำแหน่งฟังก์ชันต้องตรงกับตำแหน่งบริการ SQL Connect เพื่อให้เหตุการณ์ทริกเกอร์ฟังก์ชัน โดยค่าเริ่มต้น ภูมิภาคฟังก์ชันคือ 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

กรองเหตุการณ์

คุณกำหนดค่าตัวแฮนเดิล onMutationExecuted ด้วยตัวเลือกเพื่อกรองเหตุการณ์ตามแอตทริบิวต์ที่เฉพาะเจาะจงได้ ซึ่งจะมีประโยชน์เมื่อคุณต้องการทริกเกอร์ฟังก์ชันสำหรับ Mutation บางรายการเท่านั้น

คุณสามารถกรองตาม 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

ระบบจะป้อนข้อมูลประเภทการตรวจสอบสิทธิ์และรหัสการตรวจสอบสิทธิ์ดังนี้

Mutation เริ่มต้นโดย authtype authid
ผู้ใช้ปลายทางที่ได้รับการตรวจสอบสิทธิ์ 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 Enum ที่แสดงถึงประเภทของพรินซิเพิลที่ทริกเกอร์เหตุการณ์
authId string ตัวระบุที่ไม่ซ้ำกันของพรินซิเพิลที่ทริกเกอร์เหตุการณ์
data MutationEventData เพย์โหลดของเหตุการณ์ SQL Connect ดูส่วนถัดไป

เพย์โหลดข้อมูล

ออบเจ็กต์ MutationEventData มีเพย์โหลดของ 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: ออบเจ็กต์ที่มีตัวแปรที่ส่งไปยัง Mutation
  • payload.data: ออบเจ็กต์ที่มีข้อมูลที่ Mutation ส่งคืน
  • payload.errors: อาร์เรย์ของข้อผิดพลาดที่เกิดขึ้นระหว่างการดำเนินการ Mutation หาก Mutation สำเร็จ อาร์เรย์นี้จะว่างเปล่า

ตัวอย่าง

วิธีเข้าถึงตัวแปร Mutation และข้อมูลที่ส่งคืน

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

โปรดทราบว่าเหตุการณ์ SQL Connect ไม่ได้ให้ข้อมูลสแนปชอต "ก่อน" ของข้อมูล ซึ่งแตกต่างจากทริกเกอร์ฐานข้อมูลอื่นๆ เช่น Cloud Firestore หรือ Realtime Database เนื่องจาก SQL Connect พร็อกซีคำขอไปยัง ฐานข้อมูลพื้นฐาน จึงไม่สามารถรับข้อมูลสแนปชอต "ก่อน" ของข้อมูลได้ แบบทรานแซ็กชัน แต่คุณจะเข้าถึงอาร์กิวเมนต์ที่ส่งไปยัง Mutation และข้อมูลที่ Mutation ส่งคืนได้

ผลที่ตามมาอย่างหนึ่งคือ คุณไม่สามารถใช้กลยุทธ์การเปรียบเทียบข้อมูลสแนปชอต "ก่อน" และ "หลัง" เพื่อหลีกเลี่ยงลูปไม่สิ้นสุด ซึ่งทริกเกอร์เหตุการณ์จะทริกเกอร์เหตุการณ์เดียวกัน หากต้องดำเนินการ Mutation จากฟังก์ชันที่ทริกเกอร์โดยเหตุการณ์ Mutation ให้ใช้ตัวกรองเหตุการณ์และระมัดระวังไม่ให้ Mutation ทริกเกอร์ตัวเองได้ แม้จะเป็นการทริกเกอร์ทางอ้อมก็ตาม