يوضّح لك هذا الدليل كيفية نقل إضافاتك من بيئة Firebase Extensions التي تم إيقافها نهائيًا إلى دالة يثبّتها المستخدمون وينشرونها في قاعدة الرموز البرمجية الخاصة بهم في Cloud Functions لـ Firebase (الجيل الثاني).
هذا هو مسار نقل البيانات الموصى به. Firebase ستحتفظ بقائمة من الإضافات التي تتضمّن بدائل رسمية على npm، وسيرشدك هذا الدليل إلى كيفية إنشاء إضافتك.
في هذا الدليل، يتم استخدام إضافة Stream Firestore to 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مَعلمة محدّدة في رمز الحزمة.أدوار "إدارة الهوية وإمكانية الوصول" (IAM) التصريحية وواجهات برمجة التطبيقات المطلوبة. يصبح كل دور تُعلن عنه في
extension.yamlاستدعاءً لـrequiresRole(...)، وتصبح كل واجهة برمجة تطبيقات استدعاءً لـrequiresAPI(...)في رمز الدالة. عند النشر، تمنح Firebase CLI الأدوار المُعلَن عنها لحساب خدمة وقت التشغيل المُدار وتفعِّل واجهات برمجة التطبيقات المُعلَن عنها نيابةً عنك.أحداث مراحل النشاط لقواعد رموز Cloud Functions. تتوافق Cloud Functions قواعد الرموز الآن مع أحداث مراحل النشاط المشابهة لـ Firebase Extensions. يمكنك الإعلان عن الإعدادات في وقت التثبيت ووقت التعديل باستخدام خطافَي مراحل النشاط
afterFirstDeploy(...)وafterRedeploy(...). يحلّ هذان الخطافان محلّlifecycleEventsالتي تُعلن عنها فيextension.yaml.
جرد الإضافة
ابدأ بإجراء جرد لإضافتك: قائمة كاملة بكل ما تُعلنه الإضافة وتُرسله وتوثّقه، بحيث يكون لكل سلوك وجهة محدّدة في دالة الجيل الثاني ولا يتم فقدان أي شيء أثناء عملية نقل البيانات.
راجِع كلًّا مما يلي، ولاحِظ ما تجده:
extension.yaml: يُعلن عن المَعلمات والدوال والأحداث وأدوار "إدارة الهوية وإمكانية الوصول" وواجهات برمجة التطبيقات المطلوبة والأسرار وخطافَي مراحل النشاط.functions/: يحتوي على رمز الدالة والتبعيات وإعدادات الإصدار والمشغلات وقائمة انتظار المهام.README.mdوPREINSTALL.mdوPOSTINSTALL.md: تحتوي على خطوات الإعداد والتحذيرات وملاحظات الفوترة.scripts/: يحتوي على أي أدوات استيراد أو إعادة ملء أو "إدارة الهوية وإمكانية الوصول" أو إصلاح أو نقل بيانات، وأي أدوات أخرى تُرسلها مع الإضافة.
بعد ذلك، حدِّد مكان كل عنصر في
extension.yaml، حدِّد مكانها
في حزمة npm:
تحويل إعدادات المستخدم إلى مَعلمات Cloud Functions (القسم 5)
تحويل الأسرار إلى Cloud Functions أسرار (القسم 6)
تحويل أدوار "إدارة الهوية وإمكانية الوصول" إلى إعلانات
requiresRole(...)(القسم 8)تحويل واجهات برمجة التطبيقات المطلوبة من Google إلى إعلانات
requiresAPI(...)عند الاقتضاء (القسم 8)تحويل خطافَي التثبيت والتعديل إلى إعلانات
afterFirstDeploy(...)وafterRedeploy(...)(القسم 8)
مثال عملي: Stream Firestore to BigQuery
تؤدي قراءة firestore-bigquery-export/extension.yaml وfunctions/ إلى هذا الجرد:
| في extension.yaml | العدد / القيمة | مكان وضعها |
|---|---|---|
| params | 25 (COLLECTION_PATH وDATASET_ID وTABLE_ID وDATASET_LOCATION وVIEW_TYPE وما إلى ذلك) | Cloud Functions مَعلمات (القسم 5) |
| apis | bigquery.googleapis.com | requiresAPI(...) (القسم 7) |
| roles | bigquery.dataEditor وdatastore.user وbigquery.user | requiresRole(...) (القسم 7) |
| resources | دالة تشغيل حدث واحدة (fsexportbigquery) + دوال قائمة انتظار المهام (initBigQuerySync وsetupBigQuerySync) | دوال الحزمة المُصدَّرة (القسم 3) |
| lifecycleEvents | onInstall ← initBigQuerySync وonUpdate / onConfigure ← setupBigQuerySync | afterFirstDeploy / afterRedeploy (القسم 9) |
| scripts/ | import/ (إعادة الملء) وgen-schema-view/ | يتم الاحتفاظ بها كنصوص برمجية (خارج نطاق هذا الدليل) |
لا تُعلن الإضافة عن أي مَعلمات من النوع secret، لذا ليس هناك ما يجب نقله في القسم 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) التي تم استخدامها لكتابة مكتبتك.
مثال عملي: Stream Firestore to BigQuery
قبل إنّ ملف functions/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) للجيل الثاني تعرض الآن مَعلمات الإصدار الأول كحقول في عنصر الحدث ما يسمح لك باستخدام مَعلمات تم إلغاء بنيتها أو مَعلمات مُسمّاة والحفاظ على منطق نشاطك التجاري بدون تغيير.
قبل الجيل الأول:
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 CLI مَعلماتك وتقرأ قيمها من .env، .env.projectId، أو تطلب من المستخدمين إدخالها أثناء النشر. احتفِظ بأسماء المَعلمات نفسها، بحيث يتم نقل القيم من عملية التثبيت الحالية.
من المهم عدم تغيير أسماء المَعلمات المُعلَن عنها في الرمز على الإطلاق. سيؤدي نقل الإضافة إلى الاحتفاظ تلقائيًا بقيمة المَعلمة الحالية للمستخدم النهائي، ولكن فقط عندما تكون الأسماء بدون تغيير.
مثال عملي: Stream Firestore to BigQuery
قبل مَعلمة مُعلَن عنها في 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، يمكنك الإعلان عن الأسرار باستخدام `type: 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 الخاص بالمستخدم النهائي. من المهم عدم تغيير أسماء الأسرار المُعلَن عنها في الرمز على الإطلاق. أثناء عملية نقل البيانات، سيتم نقل أسرار المستخدم النهائي وفقًا لذلك.
مثال عملي: Trigger Email From 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 واحدة: تكتشف واجهة سطر الأوامر كلتَيهما وتقرأهما من .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 تتطلب من الإضافات تمرير معرّف مثيل الإضافة الخاص بها كمعلَمة ثانية لاستهداف دالة "قائمة المهام" في الإضافة نفسها. اعتبارًا من `firebase-admin` 14.2.0، لم يعد ذلك مطلوبًا ولا يُنصح به. ستستهدف Task Queue API الآن قوائم المهام في السياق نفسه (مثل الإضافة) تلقائيًا. من الآمن والمشجّع إزالة هذه المَعلمة في الرمز سواء كإضافة أو كدوال مستقلة. تضمن إزالة هذه المَعلمة إمكانية النقل والتوافق مع الإصدارات المستقبلية.
تظل كل العناصر الأخرى المتعلقة باستدعاء الإضافة إلى قائمة المهام كما هي، بما في ذلك مسار المرجع للمواقع الجغرافية/region/الدوال/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).
الإعلان عن واجهات برمجة التطبيقات المطلوبة وأدوار "إدارة الهوية وإمكانية الوصول"
يمكنك نقل متطلبات "إدارة الهوية وإمكانية الوصول" وواجهات برمجة التطبيقات الخاصة بإضافتك من extension.yaml إلى الرمز:
import { requiresAPI, requiresRole } from "firebase-functions"
requiresAPI("bigquery.googleapis.com", "Needed to write changelog rows");
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/bigquery.user");
باستخدام الأمان التصريحي، تنشئ Firebase CLI حساب خدمة وقت تشغيل مُدارًا لقاعدة الرموز أو تعدّله، وتمنحه اتحاد جميع الأدوار المُعلَن عنها. يمكنك توضيح للمستخدمين أنّ جميع الدوال في قاعدة الرموز تعمل بهذه الأدوار، ما لم تكن واجهة برمجة التطبيقات النهائية تتيح نموذجًا أضيق نطاقًا.
مثال عملي: Stream Firestore to 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
مثال عملي: Stream Firestore to 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 التي تفعِّلها الحزمة أو تتطلبها
خطافَي مراحل النشاط اللذَين تُعلنهما الحزمة وكيفية إعادة تشغيلهما يدويًا
ملاحظات الفوترة
التغييرات التي تم إجراؤها مقارنةً بالإضافة الأصلية
مثال عملي: Stream Firestore to BigQuery
يُرسِل ملف README الخاص بالحزمة جدولًا ملموسًا يوضّح "ما الذي تغيّر":
| حسب حالة العين | بصفتها الإضافة | بصفتها @firebase/firestore-bigquery-export |
|---|---|---|
| الإعداد | مَعلمات الإضافة | مَعلمات الدوال من خلال .env |
| إدارة الهوية وإمكانية الوصول | تم منحها بواسطة "الإضافات" | requiresRole(...)، يتم تطبيقها عند النشر |
| إدارة الحسابات | مهمة مراحل النشاط بواسطة "الإضافات" | مهمة afterFirstDeploy / afterRedeploy |
| أسماء الدوال | ext-instanceId-fsexportbigquery | fsexportbigquery (مع بادئة اختيارية) |
اختبار دالة الجيل الثاني
يجب أن يكون لديك الآن دالة من الجيل الثاني، وعند نشرها، ستتصرّف تمامًا مثل عملية تثبيت جديدة لإضافتك. الخطوة الأخيرة هي التحقّق من أي مشاكل تم إدخالها عن طريق الخطأ وإصلاحها.
تأكَّد من استخدام
firebase-tools
>= 15.25.1، وانشر دالة الجيل الثاني المحوّلة في مشروع اختبار
يتضمّن الموارد المناسبة لاختبار سلوكها. إذا سبق لك إعداد مشروع اختبار من اختبار إضافتك، استخدِم الأمر:
firebase deploy --only functions
بعد إدخال هذا الأمر، املأ المعالج الناتج الذي يطلب منك قيم المَعلمات بالطريقة نفسها التي كنت ستملأ بها نموذج التثبيت في Firebase console للإضافة.
مثال عملي: Stream Firestore to BigQuery
نتحقّق من عملية المزامنة من Cloud Firestore إلى BigQuery بشكلٍ كامل:
- في Cloud Firestore console، أنشئ المجموعة التي ضبطتها على COLLECTION_PATH (المستخدمون) إذا لم تكن موجودة.
- أنشئ مستندًا باسم bigquery-mirror-test يحتوي على أي حقول بأي قيم.
- في BigQuery console، استعلم عن جدول سجلّ التغييرات الأولي. يجب أن يحتوي على صف واحد يسجّل عملية إنشاء المستند:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
- استعلم عن آخر طريقة عرض، التي يجب أن تعرض آخر حدث تغيير لـ
المستند الوحيد الحالي:
bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
- احذف المستند
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-<instanceId>-fsexportbigquery. ابحث عن هذا الاسم في الـ Cloud Functions dashboard وسجلّاتها. - سيعمل الرمز الآن في الـ Firebase Local Emulator Suite كدوال عادية. يمكنك ضبط قيمة المَعلمات لاستخدامها في المحاكي باستخدام
.env.local. يمكنك أيضًا إجراء اختبار الوحدة للرمز باستخدام حزمة firebase-functions-test SDK كما هو موضّح في اختبار الوحدة في Cloud Functions - لم يعد وقت تشغيل "الإضافات" هو الذي يشغّل عملية توفير الموارد. إذا كان جدول سجلّ التغييرات غير متوفّر بعد النشر، أعِد تشغيل مهمة الإعداد يدويًا:
firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME. المهمة غير حساسة للتكرار، لذا تؤدي إعادة تشغيلها إلى مطابقة مجموعة البيانات والجدول وطرق العرض. - تأتي قيم المَعلمات من
.envبدلاً من نموذج التثبيت، لذا لن تكون عمليات إعادة تشغيلfirebase deployتفاعلية بعد إكمال.env.