آماده‌سازی افزونه‌های فایربیس برای مهاجرت به توابع ابری

این راهنما به شما نشان می‌دهد که چگونه افزونه‌های خود را از محیط منسوخ‌شده‌ی Firebase Extensions به تابعی که کاربران شما نصب و در پایگاه کد Cloud Functions for 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 ارسال کنید، که با یک ایمیل درخواست عضویت پاسخ داده خواهد شد. شما باید به آن ایمیل پاسخ دهید، نه اینکه روی دکمه "Join This Group" کلیک کنید.

قبل از اینکه شروع کنی

برای تکمیل این مهاجرت، از ویژگی‌های زیر در Cloud Functions استفاده خواهید کرد:

  • پیکربندی پارامتری . هر پارامتری که در extension.yaml تعریف می‌کنید، به یک پارامتر تعریف‌شده در کد بسته شما تبدیل می‌شود.

  • نقش‌های IAM اعلانی و APIهای مورد نیاز. هر نقشی که در extension.yaml اعلان می‌کنید، به یک فراخوانی requiresRole(...) تبدیل می‌شود و هر API در کد تابع شما به یک فراخوانی requiresAPI(...) تبدیل می‌شود. در زمان استقرار، Firebase CLI نقش‌های اعلان‌شده را به یک حساب سرویس زمان اجرای مدیریت‌شده اعطا می‌کند و APIهای اعلان‌شده را از طرف شما فعال می‌کند.

  • رویدادهای چرخه عمر برای پایگاه‌های کد Cloud Functions . پایگاه‌های کد Cloud Functions اکنون از رویدادهای چرخه عمر مشابه Firebase Extensions پشتیبانی می‌کنند. تنظیمات زمان نصب و زمان به‌روزرسانی را با قلاب‌های چرخه عمر afterFirstDeploy(...) و afterRedeploy(...) اعلام کنید. این‌ها جایگزین lifecycleEvents می‌شوند که شما در extension.yaml اعلام می‌کنید.

موجودی افزونه را بررسی کنید

با تهیه فهرستی از افزونه خود شروع کنید: یک لیست کامل از هر چیزی که افزونه اعلام می‌کند، ارسال می‌کند و مستند می‌کند، به طوری که هر رفتار در تابع نسل دوم یک مقصد مشخص داشته باشد و هیچ چیز در مهاجرت از دست نرود.

هر یک از موارد زیر را بررسی کنید و آنچه را که پیدا می‌کنید یادداشت کنید:

  • extension.yaml که پارامترها، توابع، رویدادها، نقش‌های IAM، APIهای مورد نیاز، رمزها و هوک‌های چرخه عمر شما را تعریف می‌کند.

  • functions/ که شامل کد تابع، وابستگی‌ها، پیکربندی ساخت، تریگرها و توابع صف وظایف شما می‌شود.

  • README.md ، PREINSTALL.md و POSTINSTALL.md که شامل مراحل راه‌اندازی، هشدارها و یادداشت‌های صورتحساب هستند.

  • scripts/ که شامل هرگونه ابزار import، backfill، IAM، repair یا migration و هر ابزار دیگری است که شما در کنار افزونه ارائه می‌دهید.

سپس، برای هر آیتم در extension.yaml ، تصمیم بگیرید که در کجای پکیج npm قرار گیرد:

  • تبدیل پیکربندی کاربر به پارامترهای Cloud Functions (بخش ۵).

  • تبدیل اسرار به اسرار Cloud Functions (بخش 6).

  • نقش‌های IAM را به اعلان‌های requiresRole(...) تبدیل کنید (بخش 8).

  • در صورت لزوم، APIهای مورد نیاز گوگل را به اعلان‌های requiresAPI(...) تبدیل کنید (بخش ۸).

  • قلاب‌های نصب و به‌روزرسانی را به اعلان‌های afterFirstDeploy(...) و afterRedeploy(...) تبدیل کنید (بخش 8).

مثال کار شده: انتقال Firestore به BigQuery

خواندن firestore-bigquery-export/extension.yaml و functions/ این فهرست را تولید می‌کند:

در extension.yaml تعداد / مقدار کجا می رود؟
پارامترها ۲۵ (مسیر مجموعه، شناسه مجموعه داده، شناسه جدول، مکان مجموعه داده، نوع نمایش، ...) پارامترهای Cloud Functions (بخش ۵)
رابط‌های برنامه‌نویسی کاربردی (APIS) bigquery.googleapis.com requireAPI(...) (بخش 7)
نقش‌ها bigquery.dataEditor، datastore.user، bigquery.user requireRole(...) (بخش 7)
منابع ۱ رویداد ماشه (fsexportbigquery) + توابع صف وظایف (initBigQuerySync، setupBigQuerySync) توابع بسته صادر شده (بخش 3)
رویدادهای چرخه حیات onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync afterFirstDeploy / afterRedeploy (بخش 9)
اسکریپت‌ها/ import/ (پر کردن مجدد)، gen-schema-view/ به عنوان اسکریپت نگهداری می‌شود (خارج از محدوده اینجا)

این افزونه هیچ پارامتر type: secret را اعلام نمی‌کند، بنابراین در بخش ۶ این راهنما چیزی برای مهاجرت وجود ندارد. تریگر رویداد از قبل نسل دوم است؛ فقط توابع صف وظایف هنوز نسل اول هستند (مرتبط با بخش ۳).

به‌روزرسانی 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 را علاوه بر وابستگی عادی خود، به عنوان یک وابستگی همتا تعریف کنید، به طوری که پروژه Cloud Functions کاربران شما همان نسخه SDK را داشته باشد که کتابخانه شما با آن نوشته شده است.

مثال کار شده: انتقال Firestore به BigQuery

قبل از. فایل functions/package.json افزونه private است، شناسه افزونه را نامگذاری می‌کند و 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/... وارد کنید و تنظیمات زمان اجرا را در گزینه‌های تابع وارد کنید.

شما می‌توانید با استفاده از قابلیت تجزیه و تحلیل رویداد (event destructuring) در نسل دوم، تلاش‌های بازنویسی را به حداقل برسانید و از بازنویسی منطق تابع خود جلوگیری کنید، زیرا SDK نسل دوم اکنون پارامترهای V1 را به عنوان فیلدهایی در شیء رویداد نمایش می‌دهد و به شما امکان می‌دهد از پارامترهای تجزیه شده/نام‌گذاری شده استفاده کنید و منطق کسب‌وکار خود را بدون تغییر نگه دارید.

قبل از. نسل اول:

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() برای خواندن رشته درون یک handler استفاده کنید؛ collectionPath مستقیماً در جایی که انتظار می‌رود یک placeholder وجود داشته باشد، مانند مسیر تریگر تابع، استفاده کنید.

رابط خط Firebase پارامترهای شما را کشف می‌کند و مقادیر آنها را از .env، projectId می‌خواند، یا در حین استقرار از کاربران شما درخواست می‌کند. نام پارامترها را یکسان نگه دارید تا مقادیر از یک نصب موجود به نصب بعدی منتقل شوند.

مهم است که به هیچ وجه نام پارامترهای اعلام شده در کد خود را تغییر ندهید . مهاجرت افزونه، مقدار پارامترهای موجود کاربر نهایی را به طور خودکار حفظ می‌کند، اما فقط زمانی که نام‌ها بدون تغییر باشند.

مثال عملی: استریم Firestore به 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، شما secretها را با نوع: secret تعریف می‌کنید. زمان اجرای Extensionها آنها را ذخیره و bind می‌کند، بنابراین کد extension شما می‌تواند process.env.PARAM_NAME را مستقیماً بخواند. در یک پایگاه کد معمولی Cloud Functions ، شما هر secret را به صراحت تعریف و bind می‌کنید:

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 ؛ رابط خط فرمان هر دو را کشف کرده و از .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 از افزونه‌ها می‌خواستند که شناسه نمونه افزونه خود را به عنوان پارامتر دوم برای هدف قرار دادن یک تابع Task Queue در همان افزونه ارسال کنند. از نسخه `firebase-admin` 14.2.0، این کار نه الزامی است و نه توصیه می‌شود. API Task Queue اکنون به طور پیش‌فرض صف‌های وظیفه را در همان زمینه (مثلاً افزونه) هدف قرار می‌دهد. حذف این پارامتر در کد شما، چه به عنوان یک افزونه و چه به عنوان توابع مستقل، ایمن و توصیه می‌شود. حذف این پارامتر، قابلیت حمل و سازگاری رو به جلو را تضمین می‌کند.

هر چیز دیگری در مورد فراخوانی enqueue - مسیر منبع locations/ region /functions/ name ، بار وظیفه و منطق تلاش مجدد شما - بدون تغییر باقی می‌ماند.

برای جزئیات بیشتر در مورد در صف قرار دادن توابع با Cloud Tasks به /docs/functions/task-functions مراجعه کنید.

قبل از. پسوند نسل اول

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";
import { region } from "firebase-functions/params";

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

اگر فراخوانی enqueue شما یک کدبیس پیشوندی را هدف قرار دهد، نام تابع کشف شده نیز پیشوندی می‌شود (برای مثال، orders-syncBigQuery ).

APIها و نقش‌های IAM مورد نیاز را اعلام کنید

الزامات IAM و API افزونه خود را از فایل 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 یک حساب سرویس زمان اجرای مدیریت‌شده برای کدبیس ایجاد یا به‌روزرسانی می‌کند و به آن اجازه می‌دهد تا تمام نقش‌های اعلان‌شده را در یکجا داشته باشد. برای کاربران خود مستند کنید که تمام توابع موجود در کدبیس با آن نقش‌ها اجرا می‌شوند، مگر اینکه API نهایی از مدل محدودتری پشتیبانی کند.

مثال کار شده: انتقال Firestore به BigQuery

قبلاً. در فایل extension.yaml تعریف شده بود؛ زمان اجرای Extensions، API را فعال کرده و نقش‌ها را به یک حساب مدیریت‌شده اعطا می‌کرد:

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

بعد از آن. در کد با requireAPI و 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 ، که توسط زمان اجرای Extensions هدایت می‌شود:

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 که بسته به آنها نیاز دارد.

  • اسراری که بسته به آنها نیاز دارد و نحوه انتقال مقادیر مخفی موجود.

  • نقش‌های IAM که پکیج با requiresRole(...) اعلام می‌کند.

  • APIهای گوگل که بسته فعال می‌کند یا به آنها نیاز دارد.

  • هوک‌های چرخه عمری که پکیج اعلام می‌کند، و نحوه‌ی اجرای مجدد آنها به صورت دستی.

  • یادداشت‌های صورتحساب.

  • چه چیزی در مقایسه با افزونه اصلی تغییر کرده است.

مثال کار شده: انتقال Firestore به BigQuery

فایل README پکیج، یک جدول «چه چیزهایی تغییر کرده» ارائه می‌دهد:

نگرانی به عنوان پسوند به عنوان @firebase/firestore-bigquery-export
پیکربندی پارامترهای افزونه پارامترهای توابع از طریق .env
آی ام اعطا شده توسط افزونه‌ها requireRole(...)، در زمان استقرار اعمال می‌شود.
تأمین وظیفه چرخه عمر توسط افزونه‌ها وظیفه afterFirstDeploy / afterRedeploy
نام توابع ext- instanceId -fsexportbigquery fsexportbigquery (پیشوند اختیاری)

عملکرد نسل دوم خود را آزمایش کنید

اکنون باید یک تابع نسل دوم داشته باشید که پس از استقرار، دقیقاً مانند نصب جدید افزونه شما رفتار خواهد کرد. آخرین مرحله، تأیید و رفع هرگونه مشکلی است که به طور تصادفی در طول مسیر ایجاد شده است.

مطمئن شوید که از firebase-tools >= 15.24.0 استفاده می‌کنید و تابع نسل دوم تبدیل‌شده‌ی خود را در یک پروژه‌ی آزمایشی با منابع مناسب مستقر کنید تا رفتار آن را آزمایش کنید. اگر از قبل یک پروژه‌ی آزمایشی از آزمایش افزونه‌ی خود راه‌اندازی کرده‌اید، از دستور زیر استفاده کنید:

firebase deploy --only functions

پس از وارد کردن این دستور، ویزارد حاصل را که مقادیر پارامترهای for را از شما می‌پرسد، پر کنید، همانطور که فرم نصب را در کنسول 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 (که به صورت اختیاری با پیشوند codebase-prefix مشخص می‌شود) مستقر می‌شود، نه ext-&lt;instanceId&gt;-fsexportbigquery . آن نام را در داشبورد و گزارش‌های Cloud Functions جستجو کنید.
  • اکنون کد شما در Firebase Local Emulator Suite به عنوان توابع عادی اجرا خواهد شد. می‌توانید مقدار پارامترهایی را که در شبیه‌ساز استفاده می‌شوند با .env.local تنظیم کنید. همچنین می‌توانید کد خود را با استفاده از firebase-functions-test SDK همانطور که در بخش تست واحد Cloud Functions توضیح داده شده است، تست واحد کنید.
  • تأمین منابع دیگر توسط زمان اجرای Extensions هدایت نمی‌شود. اگر جدول گزارش تغییرات پس از استقرار از دست رفته باشد، وظیفه راه‌اندازی را به صورت دستی دوباره اجرا کنید: firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME . این وظیفه خودتوان است، بنابراین اجرای مجدد آن، مجموعه داده‌ها، جدول و نماها را تطبیق می‌دهد.
  • مقادیر پارامتر به جای فرم نصب، از .env ‎ می‌آیند، بنابراین اجرای مجدد firebase deploy پس از تکمیل فایل .env ‎ غیرتعاملی خواهد بود.