إعداد "إضافات Firebase" لنقل البيانات إلى "وظائف السحابة الإلكترونية"

يوضّح لك هذا الدليل كيفية نقل إضافاتك من بيئة Firebase Extensions المتوقّفة نهائيًا إلى دالة يثبّتها المستخدمون وينشرونها في Cloud Functions الخاص بهم من أجل قاعدة الرموز البرمجية Firebase (الجيل الثاني).

هذا هو مسار نقل البيانات المقترَح. ستحتفظ Firebase بقائمة بالإضافات التي تتضمّن بدائل رسمية في npm، وسيرشدك هذا الدليل إلى كيفية إنشاء إضافتك.

في هذا الدليل، يتم استخدام إضافة نقل البيانات من Firestore إلى BigQuery (firestore-bigquery-export) كمثال. ينتهي كل قسم بمثال محلول يوضّح الشكل الذي كانت عليه الإضافة قبل عملية النقل والشكل الذي أصبحت عليه بعد عملية النقل، أي حزمة ‎@firebase/firestore-bigquery-export.

الاشتراك للحصول على مزيد من المعلومات والمساعدة بشأن نقل الإضافات

إذا كانت لديك أسئلة حول كيفية نقل البيانات من Firebase Extensions، يمكنك التواصل معنا على firebase-extensions-migrator-support-external@google.com. سنرسل أيضًا رسالة إلكترونية إلى هذه المجموعة عند تعديل الدليل وإضافة المزيد من المعلومات حول تجميع وظائف الجيل الثاني واختبارها وتوزيعها.

للانضمام إلى هذه المجموعة، أرسِل رسالة إلى firebase-extensions-migrator-support-external+subscribe@google.com، وسيتم الردّ عليك برسالة إلكترونية تتضمّن طلبًا للانضمام. عليك الرد على تلك الرسالة الإلكترونية، وليس النقر على الزر "الانضمام إلى هذه المجموعة".

قبل البدء

لإكمال عملية النقل هذه، ستستخدم الميزات التالية في Cloud Functions:

  • الإعدادات التي تتضمّن مَعلمات: تصبح كل مَعلمة تعرّفها في extension.yaml مَعلمة محدّدة في رمز الحزمة.

  • أدوار "إدارة الهوية وإمكانية الوصول" التعريفية وواجهات برمجة التطبيقات المطلوبة يصبح كل دور تحدّده في extension.yaml طلب requiresRole(...)، وتصبح كل واجهة برمجة تطبيقات طلب requiresAPI(...) في رمز الدالة. عند النشر، تمنح أداة سطر الأوامر Firebase الأدوار المحدّدة لحساب خدمة وقت التشغيل المُدارة، وتفعّل واجهات برمجة التطبيقات المحدّدة بالنيابة عنك.

  • أحداث مراحل النشاط لقواعد الرموز Cloud Functions تتيح قواعد الرموز Cloud Functions الآن أحداث مراحل النشاط المشابهة لـ Firebase Extensions. عليك الإفصاح عن إعدادات وقت التثبيت ووقت التحديث باستخدام خطافات مراحل النشاط afterFirstDeploy(...) وafterRedeploy(...). تحلّ هذه السمة محل lifecycleEvents التي تحدّدها في extension.yaml.

جرد الإضافة

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

راجِع كلّاً ممّا يلي، ودوِّن ما تجده:

  • extension.yaml، الذي يحدّد المَعلمات والدوال والأحداث وأدوار إدارة الهوية وإمكانية الوصول وواجهات برمجة التطبيقات المطلوبة والأسرار وخطافات مراحل النشاط.

  • functions/، الذي يحتوي على رمز الدالة والتبعيات وإعدادات الإنشاء والمشغّلات ودوال قائمة انتظار المهام.

  • README.md وPREINSTALL.md وPOSTINSTALL.md، التي تتضمّن خطوات الإعداد والتحذيرات وملاحظات الفوترة

  • scripts/، الذي يحتوي على أي أدوات استيراد أو إعادة تعبئة أو إدارة هوية وإمكانية الوصول أو إصلاح أو نقل، وأي أدوات أخرى يتم شحنها مع الإضافة

بعد ذلك، حدِّد مكان كل عنصر في حزمة npm ضمن extension.yaml:

  • تحويل إعدادات المستخدم إلى مَعلمات Cloud Functions (القسم 5)

  • حوِّل الأسرار إلى أسرار Cloud Functions (الفقرة 6).

  • تحويل أدوار "إدارة الهوية وإمكانية الوصول" إلى تصريحات requiresRole(...) (الفقرة 8)

  • تحويل واجهات Google APIs المطلوبة إلى تصريحات requiresAPI(...) عند الاقتضاء (الفقرة 8)

  • تحويل خطافات التثبيت والتحديث إلى بيانات afterFirstDeploy(...) وafterRedeploy(...) (الفقرة 8)

مثال عملي: بث بيانات Firestore إلى BigQuery

تؤدي قراءة firestore-bigquery-export/extension.yaml وfunctions/ إلى إنشاء هذا المستودع:

في ملف extension.yaml العدد / القيمة مكان ظهورها
المَعلمات ‫25 (COLLECTION_PATH وDATASET_ID وTABLE_ID وDATASET_LOCATION وVIEW_TYPE وما إلى ذلك) مَعلمات Cloud Functions (القسم 5)
واجهات برمجة التطبيقات bigquery.googleapis.com requiresAPI(...) (الفقرة 7)
الأدوار bigquery.dataEditor وdatastore.user وbigquery.user requiresRole(...) (الفقرة 7)
المراجع مشغّل حدث واحد (fsexportbigquery) + وظائف قائمة انتظار المهام (initBigQuerySync وsetupBigQuerySync) دوال الحزمة التي تم تصديرها (القسم 3)
lifecycleEvents onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync afterFirstDeploy / afterRedeploy (القسم 9)
scripts/ import/ (backfill), gen-schema-view/ يتم الاحتفاظ بها كنصوص برمجية (خارج نطاق هذا المستند)

لا تحدّد الإضافة أي نوع: مَعلمات سرية، لذا لا يوجد أي شيء لنقله في القسم 6 من هذا الدليل. مشغّل الحدث هو الجيل الثاني، أما وظائف قائمة انتظار المهام فهي الجيل الأول (ذات صلة بالقسم 3).

تعديل ملف package.json

عدِّل ملف package.json الخاص بالإضافة. إذا كنت تنقل إضافة واحدة، يمكن أن يكون هذا هو الجذر package.json. إذا كنت بصدد نقل العديد من الإضافات في مستودع واحد، امنح كل إضافة حزمة خاصة بها.

الحد الأدنى لإصدارات حزمة تطوير البرامج (SDK) عليك تعريف firebase-functions >= 7.3 وfirebase-admin >= 14.2.0 كعناصر تابعة. يجب أيضًا تعريف إصدار firebase-functions كإحدى التبعيات المتساوية

{
  "name": "<package-name>",
  "version": "1.0.0",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "exports": {
    ".": {
      "types": "./lib/index.d.ts",
      "default": "./lib/index.js"
    }
  },
  "engines": {
    "node": ">=22"
  },
  "peerDependencies": {
    "firebase-functions": "^7.3.0"
  },
  "dependencies": {
    "firebase-functions": "^7.3.0",
    "firebase-admin": "^14.2.0"
  }
}

عليك تعريف firebase-functions كإحدى التبعيات المتساوية بالإضافة إلى التبعية العادية، وذلك لكي يتضمّن مشروع Cloud Functions الخاص بالمستخدمين الإصدار نفسه من حزمة SDK التي تم إنشاء المكتبة باستخدامها.

مثال عملي: بث بيانات Firestore إلى BigQuery

قبل. تكون وظائف الإضافة/ملف package.json خاصًا، ويحدّد رقم تعريف الإضافة، ويُعرّف firebase-functions كعنصر تابع مباشر:

{
  "name": "firestore-bigquery-export",
  "main": "lib/index.js",
  "private": true,
  "dependencies": {
    "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
    "firebase-admin": "^14.2.0",
    "firebase-functions": "^6.3.2"
  }
}

بعد ذلك. حزمة قابلة للنشر: اسم ذو نطاق وخريطة عمليات تصدير، وتم نقل firebase-functions إلى peerDependencies:

{
  "name": "@firebase/firestore-bigquery-export",
  "version": "0.1.0",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "exports": {
    ".":     { "types": "./lib/index.d.ts", "default": "./lib/index.js" },  },
  "engines": { "node": ">=22" },
  "peerDependencies": { "firebase-functions": "^7.3.0" },
  "dependencies": {
      "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
      "firebase-admin": "^14.2.0",
      "firebase-functions": "^7.3.0"
    }
}

ترقية الدوال من الجيل الأول إلى الجيل الثاني

إذا كانت الإضافة لا تزال تصدّر دوال الجيل الأول، عليك تحويل كل دالة إلى ما يعادلها من الجيل الثاني. استورِد من وحدات firebase-functions/...، ومرِّر إعدادات وقت التشغيل في خيارات الدالة.

يمكنك تقليل جهود إعادة الكتابة باستخدام ميزة تصحيح أخطاء تفكيك بنية الأحداث في الجيل الثاني وتجنُّب إعادة كتابة منطق الدالة، لأنّ حزمة تطوير البرامج (SDK) من الجيل الثاني تعرض الآن مَعلمات الإصدار 1 كحقول في عنصر الحدث، ما يتيح لك استخدام المَعلمات المفكّكة أو المسماة والحفاظ على منطق نشاطك التجاري بدون تغيير.

قبل. الجيل الأول:

import * as functions from "firebase-functions/v1";

export const sync = functions.firestore
  .document("{collectionId}/{documentId}")
  .onWrite(async (change, context) => {
    await handleWrite(change.before, change.after, context.params);
  });

بعد ذلك. الجيل الثاني:

import { onDocumentWritten } from "firebase-functions/firestore";

export const syncV2 = onDocumentWritten(
  { document: "{collectionId}/{documentId}" },
  async ({change,context}) =>
    await handleWrite(change.before, change.after, context.params);
);

راجِع Cloud Functions مقارنة الإصدارات للاطّلاع على قائمة شاملة بالاختلافات بين الجيل الأول والجيل الثاني من الدوال.

تحويل مَعلمات الإضافة والأسرار

معلَمات التحويل

يصبح كل معلَمة تحدّدها في extension.yaml معلَمة Cloud Functions.

تحويل قراءات البيئة المباشرة:

const collectionPath = process.env.COLLECTION_PATH;

إلى مَعلمتَين Cloud Functions:

import { defineString } from "firebase-functions/params";
import { onDocumentWritten} from "firebase-functions/firestore";

const collectionPath = defineString("COLLECTION_PATH");

// Pass the param directly when used as a placeholder (e.g. trigger path)
export const sync = onDocumentWritten(
  { document: collectionPath },
  async (event) => {
    // Call .value() to read the string inside a handler
    const path = collectionPath.value();
    await handleWrite(path, event);
  }
);

استخدِم collectionPath.value() لقراءة السلسلة داخل معالج، واستخدِم collectionPath مباشرةً في المكان الذي يُتوقّع فيه عنصر نائب، مثل مسار مشغّل دالة.

تكتشف واجهة سطر الأوامر Firebase معلماتك وتقرأ قيمها من .env أو .env.projectId أو تطلب من المستخدمين إدخالها أثناء عملية النشر. احتفِظ بأسماء المَعلمات نفسها، حتى يتم نقل القيم من عملية تثبيت حالية.

من المهم عدم تغيير أسماء المَعلمات المحدّدة في الرمز على الإطلاق. سيؤدي نقل البيانات إلى الاحتفاظ بقيمة المَعلمة الحالية للمستخدم النهائي تلقائيًا، ولكن فقط عندما لا يتم تغيير الأسماء.

مثال عملي: بث بيانات Firestore إلى BigQuery Before معلَمة تم تعريفها في extension.yaml، ويتم قراءتها كمتغيّر بيئة أولي في config.ts:

# extension.yaml
-   param: COLLECTION_PATH
  label: Collection path
  type: string
  required: true
// functions/src/config.ts
collectionPath: process.env.COLLECTION_PATH,

بعد ذلك. جهاز واحد defineString، وتكتشفه واجهة سطر الأوامر وتقرأ منه .env:

// src/config.ts
import { defineString } from "firebase-functions/params";

collectionPath: defineString("COLLECTION_PATH", {
  label: "Collection path",
  // We now support "nonEmpty: true" to ensure a value other than the empty string
  // is entered, analagous to "required: true" in extensions.yaml
  input: { text: { nonEmpty: true} }
}),

لم يتغيّر اسم المَعلمة، لذا سيظل ملف ‎ .env الحالي يعمل.

تحويل الأسرار

في ملف extension.yaml، يمكنك تعريف الأسرار باستخدام النوع: secret. يخزّن وقت تشغيل الإضافات هذه المتغيرات ويربطها، ما يتيح لرمز الإضافة قراءة process.env.PARAM_NAME مباشرةً. في قاعدة رموز Cloud Functions النموذجية، عليك تعريف كل سر وربطه بشكل صريح:

import { defineSecret } from "firebase-functions/params";
import { onRequest } from "firebase-functions/https";

const apiKey = defineSecret("API_KEY");
export const fn = onRequest({ secrets: [apiKey] }, handler);

بعد نقل الإضافة إلى حزمة/مجموعة npm، ستتم إدارة مراجع الأسرار في ملف .env الخاص بالمستخدم النهائي. من المهم عدم تغيير أسماء الأسرار المحدّدة في الرمز على الإطلاق. أثناء نقل البيانات، سيتم نقل أسرار المستخدمين النهائيين وفقًا لذلك.

مثال عملي: إرسال رسالة إلكترونية مشغّلة من Cloud Firestore

قبل. يتم قراءة MAIL_COLLECTION وSMTP_PASSWORD كمتغيرات بيئية أولية في config.ts:

# extension.yaml
-   param: MAIL_COLLECTION
  label: Email documents collection
  type: string
  default: mail
  required: true

-   param: SMTP_PASSWORD
  label: SMTP password
  type: secret
// functions/src/config.ts
mailCollection: process.env.MAIL_COLLECTION,
smtpPassword: process.env.SMTP_PASSWORD,

بعد ذلك. جهاز defineString واحد وجهاز defineSecret واحد، ويتعرّف CLI على كليهما ويقرأ من .env

import { defineString, defineSecret } from "firebase-functions/params";
import { onDocumentWritten } from "firebase-functions/firestore";

const mailCollection = defineString("MAIL_COLLECTION",{ label: "Email documents collection",
 default: "mail"
});

const smtpPassword = defineSecret("SMTP_PASSWORD", { label: "SMTP password" });

export const processQueue = onDocumentWritten(
  { document: `${mailCollection}/{documentId}`, secrets: [smtpPassword] },
  async (event) => {
    const collection = mailCollection.value();
    const password = smtpPassword.value();
    // ...
  }
);

نقل طلبات قائمة انتظار المهام الداخلية

تضيف بعض الإضافات مهامًا إلى قوائم انتظار المهام الخاصة بها من داخل رمز الدالة، وذلك باستخدام Firebase Admin SDK. يختلف ذلك عن تلقّي مهمة تم إرسالها (يتم تناول ذلك في القسمَين وظائف الترقية وتحويل خطافات دورة الحياة). في هذا المثال، يكون الرمز هو المنتج الذي يستدعي queue.enqueue(...).

في الإصدارات السابقة من Admin SDK، كان على الإضافات تمرير رقم تعريف نسخة الإضافة الخاص بها كمعلَمة ثانية لاستهداف دالة في "قائمة المهام" ضمن الإضافة نفسها. اعتبارًا من الإصدار 14.2.0 من `firebase-admin`، لم يعُد هذا الإجراء مطلوبًا ولا يُنصح به. ستستهدف واجهة برمجة التطبيقات Task Queue API الآن قوائم انتظار المهام في السياق نفسه (مثل الإضافة) تلقائيًا. ننصحك بإزالة هذه المَعلمة من الرمز البرمجي سواء كانت إضافة أو وظائف مستقلة، لأنّ ذلك آمن. تضمن إزالة هذه المَعلمة إمكانية نقل البيانات والتوافق مع الإصدارات المستقبلية.

ستبقى جميع المعلومات الأخرى المتعلقة بطلب الإضافة إلى قائمة الانتظار كما هي، بما في ذلك مسار المورد locations/region/functions/name وحِزمة بيانات المهمة ومنطق إعادة المحاولة.

يمكنك الاطّلاع على /docs/functions/task-functions للحصول على مزيد من التفاصيل حول وضع الدوال في قائمة الانتظار باستخدام Cloud Tasks.

قبل. إضافة الجيل الأول

import { getFunctions } from "firebase-admin/functions";

const queue = getFunctions().taskQueue(
  `locations/${config.location}/functions/syncBigQuery`,
  process.env.EXT_INSTANCE_ID, // extension instance ID, injected by the runtime
);
await queue.enqueue(taskData);

بعد ذلك. إضافة الجيل الثاني

import { getFunctions } from "firebase-admin/functions";

const queue = getFunctions().taskQueue(
  `locations/${process.env.FUNCTION_REGION}/functions/syncBigQuery`);
await queue.enqueue(taskData);

إذا كان طلب الإضافة إلى قائمة الانتظار يستهدف قاعدة رموز برمجية ذات بادئة، سيتم أيضًا إضافة بادئة إلى اسم الدالة التي تم العثور عليها (على سبيل المثال، orders-syncBigQuery).

تحديد واجهات برمجة التطبيقات وأدوار "إدارة الهوية وإمكانية الوصول" المطلوبة

انقل متطلبات إدارة الهوية وإمكانية الوصول (IAM) وواجهة برمجة التطبيقات الخاصة بالإضافة من ملف extension.yaml إلى ملف code:

import { requiresAPI, requiresRole } from "firebase-functions"

requiresAPI("bigquery.googleapis.com", "Needed to write changelog rows");
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/bigquery.user");

باستخدام الأمان التعريفي، تنشئ أداة سطر الأوامر Firebase أو تعدّل حساب خدمة مُدارًا لوقت التشغيل خاصًا بقاعدة الرموز، وتمنحه اتحاد جميع الأدوار المحدّدة. وضِّح للمستخدمين أنّ جميع الدوال في قاعدة الرموز البرمجية تعمل بهذه الأدوار، ما لم تكن واجهة برمجة التطبيقات النهائية تتوافق مع نموذج أضيق.

مثال عملي: بث بيانات Firestore إلى BigQuery

قبل. يتم الإعلان عنها في ملف extension.yaml، وقد فعّل وقت تشغيل الإضافات واجهة برمجة التطبيقات ومنح الأدوار إلى حساب مُدار:

apis:
  -   apiName: bigquery.googleapis.com
roles:
  -   role: bigquery.dataEditor
  -   role: datastore.user
  -   role: bigquery.user

بعد ذلك. يتم تحديدها في الرمز باستخدام requiresAPI وrequiresRole:

import { requiresAPI, requiresRole } from "firebase-functions/";
requiresAPI("bigquery.googleapis.com",
  "Needed to write changelog rows and views");
requiresRole("roles/biguqery.dataEditor");
requiresRole("roles/datastore.user");
requiresRole("roles/bigquery.user");

تحويل عبارات ربط مراحل النشاط

إذا كانت الإضافة تستدعي getExtensions().runtime()، على سبيل المثال setProcessingState أو setFatalError، احذف عمليات الاستدعاء هذه لأنّها ستؤدي إلى طرح خطأ إذا تم استدعاؤها من دالة من الجيل الثاني تم تفعيلها بشكل عادي. يتم الآن تحديد حالة مراحل النشاط من خلال afterFirstDeploy وafterRedeploy حيث لا يتم استخدام تتبُّع الحالة هذا.

Firebase Extensions يمكن تشغيل عملية الإعداد عند تثبيت إضافة أو تحديثها أو إعادة ضبطها. في حزمة npm، حدِّد إجراءات مكافئة لدورة الحياة في الرمز البرمجي.

لإجراء عملية الإعداد لمرة واحدة:

import { afterFirstDeploy } from "firebase-functions/lifecycle";
import { onTaskDispatched } from "firebase-functions/tasks";

export const runInitialSetup = onTaskDispatched(async (request) => {
  await initializeResources(request.data);
});

afterFirstDeploy({
  task: {
    function: "runInitialSetup",
    body: {}
  }
});

بالنسبة إلى تعديلات الإعدادات أو الرموز:

import { afterRedeploy } from "firebase-functions/lifecycle";

afterRedeploy({
  task: {
    function: "runInitialSetup",
    body: { reconcile: true }
  }
});

اجعل إجراءات مراحل النشاط غير متكرّرة. قد يحتاج المستخدمون إلى إعادة تشغيلها يدويًا في حال تعذّر إرسالها أو تنفيذها:

firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME
firebase functions:lifecycle:run afterRedeploy CODEBASE_NAME

مثال عملي: بث بيانات Firestore إلى BigQuery

قبل.lifecycleEvents في extension.yaml، ويتم تشغيلها بواسطة وقت تشغيل الإضافات:

lifecycleEvents:
  onInstall:
    function: initBigQuerySync
    processingMessage: Configuring BigQuery Sync.
  onUpdate:
    function: setupBigQuerySync
    processingMessage: Configuring BigQuery Sync
  onConfigure:
    function: setupBigQuerySync
    processingMessage: Configuring BigQuery Sync

بعد ذلك. يتم تحديدها في الرمز، وتوفّر المهمة BigQuery عند النشر الأول:

import { afterFirstDeploy, afterRedeploy } from "firebase-functions/lifecycle";

afterFirstDeploy({ task: { function: "initBigQuerySync" } });
afterRedeploy({ task: { function: "setupBigQuerySync" } });

التوفير هو عملية متكررة، لذا تؤدي إعادة التشغيل إلى تسوية مجموعة البيانات والجدول وطرق العرض. يمكن للمستخدمين إعادة تشغيلها يدويًا باستخدام firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME.

إعداد المستندات للمستخدمين

  • اكتب حزمة README توضّح ما يلي على الأقل:

  • قيم .env التي تتطلّبها الحزمة

  • الأسرار التي تتطلّبها الحزمة وكيفية نقل قيم الأسرار الحالية

  • أدوار إدارة الهوية وإمكانية الوصول التي تحدّدها الحزمة باستخدام requiresRole(...)

  • واجهات Google APIs التي تتيحها الحزمة أو تتطلّبها

  • خطافات دورة الحياة التي تحدّدها الحزمة وكيفية إعادة تشغيلها يدويًا

  • ملاحظات الفوترة

  • التغييرات التي تم إجراؤها مقارنةً بالإضافة الأصلية

مثال عملي: بث بيانات Firestore إلى BigQuery

تتضمّن حزمة ملف README جدولاً محدّدًا بعنوان "التغييرات":

قلق كإضافة As ‎ @firebase/firestore-bigquery-export
الإعداد مَعلمات الإضافة معلَمات الدوال من خلال ملف ‎ .env
إدارة الهوية وإمكانية الوصول الأذونات التي تمنحها الإضافات requiresRole(...), applied at deploy
إدارة الحسابات مهمة مراحل النشاط حسب الإضافات المهمة afterFirstDeploy / afterRedeploy
أسماء الدوال ext-instanceId-fsexportbigquery fsexportbigquery (مع بادئة اختيارية)

اختبار الدالة من الجيل الثاني

من المفترض أن يكون لديك الآن دالة من الجيل الثاني، وعند نشرها، ستتصرّف بشكل مطابق لعملية تثبيت جديدة للإضافة. الخطوة الأخيرة هي التحقّق من أي مشاكل تم إدخالها عن طريق الخطأ أثناء عملية الدمج وإصلاحها.

تأكَّد من استخدام الإصدار firebase-tools >= 15.25.1، ونشر الدالة المحوَّلة من الجيل الثاني في مشروع تجريبي يتضمّن الموارد المناسبة لاختبار سلوكها. إذا سبق لك إعداد مشروع تجريبي من خلال اختبار الإضافة، استخدِم الأمر التالي:

firebase deploy --only functions

بعد إدخال هذا الأمر، املأ المعالج الناتج الذي يطلب منك قيم المَعلمات بالطريقة نفسها التي كنت ستملأ بها نموذج التثبيت في وحدة تحكّم Firebase للإضافة.

مثال عملي: بث بيانات Firestore إلى BigQuery

نتأكّد من أنّ المزامنة بين Cloud Firestore وBigQuery مشفّرة تمامًا بين الأطراف:

  1. في وحدة تحكّم Cloud Firestore، أنشئ المجموعة التي ضبطتها على COLLECTION_PATH (المستخدمون) إذا لم تكن موجودة من قبل.
  2. أنشئ مستندًا باسم bigquery-mirror-test يحتوي على أي حقول بأي قيم.
  3. في وحدة تحكّم BigQuery، استعلم عن جدول سجلّ التغيير الأولي. يجب أن يحتوي على صف واحد يسجّل عملية إنشاء المستند:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
  1. استعلم عن آخر عرض، والذي من المفترض أن يعرض آخر حدث تغيير للمستند الوحيد المتوفّر: bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
  1. احذف المستند bigquery-mirror-test في Cloud Firestore. يختفي من العرض الأخير، ويتم إلحاق حدث DELETE بجدول سجلّ التغيير الخام.

يمكنك الاطّلاع على السجلّ الكامل لمستند واحد باستخدام:

SELECT *
   FROM `PROJECT_ID.analytics.users_raw_changelog`
   WHERE document_name = "bigquery-mirror-test"
   ORDER BY timestamp ASC

الاختلافات عن اختبار الإضافة:

  • يتم نشر المشغّل على النحو التالي: fsexportbigquery (مع إضافة بادئة اختيارية لرمز البرنامج)، وليس ext-&lt;instanceId&gt;-fsexportbigquery. ابحث عن هذا الاسم في لوحة البيانات والسجلات Cloud Functions.
  • سيتم الآن تنفيذ الرمز في Firebase Local Emulator Suite كدوال عادية. يمكنك ضبط قيمة المَعلمات التي سيتم استخدامها في المحاكي باستخدام .env.local. يمكنك أيضًا إجراء اختبارات الوحدة للرمز باستخدام حزمة تطوير البرامج (SDK) الخاصة بـ firebase-functions-test كما هو موضّح في اختبار الوحدة Cloud Functions.
  • لم يعُد توفير الموارد يعتمد على وقت تشغيل الإضافات. إذا كان جدول سجلّ التغيير غير متوفّر بعد النشر، أعِد تشغيل مهمة الإعداد يدويًا: firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME. المهمة متكررة، لذا ستؤدي إعادة تشغيلها إلى تسوية مجموعة البيانات والجدول وطرق العرض.
  • تأتي قيم المَعلمات من .env بدلاً من نموذج التثبيت، لذا لن تكون عمليات إعادة تشغيل firebase deploy تفاعلية بعد اكتمال .env.