توسيع نطاق SQL Connect باستخدام Cloud Functions

باستخدام Cloud Functions for Firebase، يمكنك معالجة الأحداث في Firebase SQL Connect. Cloud Functions تتيح لك تشغيل رمز من جهة الخادم استجابةً للأحداث، مثل تنفيذ تغيير في خدمة SQL Connect الخاصة بك. ويتيح لك ذلك إضافة منطق مخصّص بدون نشر الخوادم الخاصة بك.

حالات الاستخدام الشائعة

  • مزامنة البيانات: يمكنك تكرار البيانات أو مزامنتها مع أنظمة أخرى (مثل Cloud Firestore أو BigQuery أو واجهات برمجة التطبيقات الخارجية) بعد حدوث تغيير

  • سير العمل غير المتزامن: يمكنك بدء عمليات طويلة الأمد، مثل معالجة الصور أو تجميع البيانات، بعد إجراء تغيير في قاعدة البيانات.

  • تفاعل المستخدمين: يمكنك إرسال رسائل إلكترونية أو إشعارات Cloud Messaging إلى المستخدمين بعد حدوث حدث تغيير معيّن في تطبيقك، مثل إنشاء حساب.

تفعيل دالة عند حدوث تغيير في SQL Connect

يمكنك تفعيل دالة كلّما تم تنفيذ تغيير SQL Connect باستخدام معالج الأحداث onMutationExecuted ويحدث هذا المشغّل عند تنفيذ تغيير.

دالة أساسية لحدث التغيير

المثال الأساسي التالي هو دالة تسجِّل تفاصيل أي تغيير يتم تنفيذه في خدمة 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)

عند التفعيل من جميع التغييرات في مشروعك، يجب عدم إجراء أي تغييرات في معالج المشغّل، وإلا سيحدث تكرار لا نهائي. إذا أردت إجراء تغييرات في مشغّل حدث، استخدِم خيارات الفلترة الموضّحة أدناه، وتأكَّد من أنّ التغيير لا يفعِّل نفسه.

ضبط موقع الدالة

يجب أن يتطابق موقع الدالة مع 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 باستخدام خيارات لفلترة الأحداث استنادًا إلى سمات معيّنة. ويكون ذلك مفيدًا عندما تريد تفعيل الدالة لتغييرات معيّنة فقط.

يمكنك الفلترة حسب 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 رقم تعريف رمز Firebase Auth
مستخدم نهائي لم يتم التحقّق منه unauthenticated فارغ
‫Admin SDK الذي ينتحل صفة مستخدم نهائي app_user رقم تعريف رمز 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 تعداد يمثّل نوع الجهة الرئيسية التي فعّلت الحدث.
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: عنصر يحتوي على المتغيّرات التي تم تمريرها إلى التغيير.
  • 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، لا يقدّم حدث SQL Connect لقطة "قبل" للبيانات. وبما أنّ SQL Connect يفوّض الطلبات إلى الـ قاعدة البيانات الأساسية، لا يمكن الحصول على لقطة "قبل" للبيانات بشكلٍ معاملاتي. بدلاً من ذلك، يمكنك الوصول إلى الوسيطات التي تم إرسالها إلى التغيير والبيانات التي تم عرضها من خلاله.

إحدى نتائج ذلك هي أنّه لا يمكنك استخدام استراتيجية مقارنة لقطات "قبل" و"بعد" لتجنُّب التكرار اللانهائي، حيث يفعِّل مشغّل حدث الحدث نفسه. إذا كان عليك إجراء تغيير من دالة يتم تفعيلها من خلال حدث تغيير، استخدِم فلاتر الأحداث وتأكَّد من عدم إمكانية تفعيل أي تغيير لنفسه، حتى بشكلٍ غير مباشر.