Firebase एक्सटेंशन को Cloud Functions पर माइग्रेट करने के लिए तैयार करना

इस गाइड में, आपको अपने एक्सटेंशन को अब सेवा में नहीं है Firebase Extensions एनवायरमेंट से, ऐसे फ़ंक्शन पर माइग्रेट करने का तरीका बताया गया है जिसे आपके उपयोगकर्ता, अपने Cloud Functions for Firebase (2nd gen) कोड बेस में इंस्टॉल और डिप्लॉय करते हैं.

हमारा सुझाव है कि माइग्रेशन के लिए, इस पाथ का इस्तेमाल करें. Firebase Firebase, आधिकारिक npm के बराबर वाले एक्सटेंशन की सूची बनाए रखेगा. इस गाइड में, आपको अपनी सूची बनाने का तरीका बताया जाएगा.

इस गाइड में, Stream Firestore to BigQuery एक्सटेंशन (firestore-bigquery-export) को उदाहरण के तौर पर इस्तेमाल किया गया है. हर सेक्शन के आखिर में, काम करने का उदाहरण दिया गया है. इसमें दिखाया गया है कि माइग्रेशन से पहले, वह एक्सटेंशन कैसा दिखता था और @firebase/firestore-bigquery-export पैकेज के तौर पर माइग्रेशन के बाद, वह कैसा दिखता है.

एक्सटेंशन माइग्रेट करने के बारे में ज़्यादा जानकारी और मदद पाने के लिए साइन अप करें

अगर आपको Firebase Extensions से माइग्रेट करने के तरीके के बारे में कोई सवाल पूछना है, तो हमसे firebase-extensions-migrator-support-external@google.com पर संपर्क करें. जब हम 2nd gen फ़ंक्शन को पैकेज करने, उनकी जांच करने, और उन्हें डिस्ट्रिब्यूट करने के बारे में ज़्यादा जानकारी के साथ गाइड को अपडेट करेंगे, तब हम इस ग्रुप को ईमेल भी भेजेंगे.

इस ग्रुप में शामिल होने के लिए, 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(...) की मदद से, इंस्टॉल करने के समय और अपडेट करने के समय के सेटअप का एलान करें. ये, extension.yaml में एलान किए गए lifecycleEvents की जगह लेते हैं.

एक्सटेंशन की इन्वेंट्री करना

सबसे पहले, अपने एक्सटेंशन की इन्वेंट्री करें. इसमें, एक्सटेंशन में एलान की गई, शिप की गई, और दस्तावेज़ में शामिल की गई हर चीज़ की पूरी सूची शामिल होती है. इससे, 2nd gen फ़ंक्शन में हर गतिविधि के लिए तय की गई जगह होती है. साथ ही, माइग्रेशन के दौरान कोई भी जानकारी नहीं खोती है.

इनमें से हर एक की समीक्षा करें और नोट करें कि आपको क्या मिला:

  • extension.yaml. इसमें आपके पैरामीटर, फ़ंक्शन, इवेंट, IAM रोल, ज़रूरी एपीआई, सीक्रेट, और लाइफ़साइकल हुक का एलान किया जाता है.

  • functions/. इसमें आपके फ़ंक्शन का कोड, डिपेंडेंसी, बिल्ड कॉन्फ़िगरेशन, ट्रिगर, और टास्क क्यू फ़ंक्शन शामिल होते हैं.

  • README.md, PREINSTALL.md, और POSTINSTALL.md. इनमें सेटअप के चरण, चेतावनियां, और बिलिंग से जुड़ी जानकारी शामिल होती है.

  • scripts/. इसमें इंपोर्ट, बैकफ़िल, IAM, ठीक करने या माइग्रेशन की यूटिलिटी शामिल होती हैं. साथ ही, इसमें वे सभी टूल शामिल होते हैं जिन्हें एक्सटेंशन के साथ शिप किया जाता है.

इसके बाद, extension.yaml में मौजूद हर आइटम के लिए, तय करें कि वह npm पैकेज में कहां जाएगा:

  • उपयोगकर्ता के कॉन्फ़िगरेशन को Cloud Functions पैरामीटर में बदलना (सेक्शन 5).

  • सीक्रेट को Cloud Functions सीक्रेट में बदलना (सेक्शन 6).

  • IAM रोल को requiresRole(...) एलान में बदलना (सेक्शन 8).

  • ज़रूरी Google API को, ज़रूरत के हिसाब से requiresAPI(...) एलान में बदलना (सेक्शन 8).

  • इंस्टॉल करने और अपडेट करने के हुक को afterFirstDeploy(...) और afterRedeploy(...) एलान में बदलना (सेक्शन 8).

काम करने का उदाहरण: Stream Firestore to 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)
संसाधन 1 इवेंट ट्रिगर (fsexportbigquery) + टास्क क्यू फ़ंक्शन (initBigQuerySync, setupBigQuerySync) एक्सपोर्ट किए गए पैकेज फ़ंक्शन (सेक्शन 3)
lifecycleEvents onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync afterFirstDeploy / afterRedeploy (सेक्शन 9)
scripts/ import/ (backfill), gen-schema-view/ स्क्रिप्ट के तौर पर रखा गया (यहां इसकी जानकारी नहीं दी गई है)

एक्सटेंशन में, सीक्रेट पैरामीटर के तौर पर कोई टाइप एलान नहीं किया गया है. इसलिए, इस गाइड के सेक्शन 6 में माइग्रेट करने के लिए कुछ भी नहीं है. इवेंट ट्रिगर पहले से ही 2nd gen है. सिर्फ़ टास्क क्यू फ़ंक्शन अब भी 1st gen हैं (सेक्शन 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"
    }
}

फ़ंक्शन को 1st gen से 2nd gen में अपग्रेड करना

अगर आपका एक्सटेंशन अब भी 1st gen फ़ंक्शन एक्सपोर्ट करता है, तो हर फ़ंक्शन को उसके 2nd gen के बराबर वाले फ़ंक्शन में बदलें. firebase-functions/... मॉड्यूल से इंपोर्ट करें और फ़ंक्शन के विकल्पों में रनटाइम सेटिंग पास करें.

2nd gen के पैच्ड इवेंट डीस्ट्रक्चरिंग की मदद से, फिर से लिखने की कोशिशों को कम किया जा सकता है. साथ ही, अपने फ़ंक्शन लॉजिक को फिर से लिखने से बचा जा सकता है . इसकी वजह यह है कि 2nd gen SDK टूल अब V1 पैरामीटर को इवेंट ऑब्जेक्ट में फ़ील्ड के तौर पर दिखाता है. इससे, डीस्ट्रक्चर्ड/नाम वाले पैरामीटर का इस्तेमाल किया जा सकता है और अपने कारोबार के लॉजिक को बदला नहीं जा सकता.

इससे पहले. 1st gen:

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);
  });

इसके बाद. 2nd gen:

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

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

1st gen और 2nd gen फ़ंक्शन के बीच के अंतर की पूरी सूची देखने के लिए, 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 का इस्तेमाल करें. जैसे, फ़ंक्शन ट्रिगर पाथ.

The 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. CLI इसे ढूंढता है और .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 के साथ सीक्रेट का एलान किया जाता है. Extensions रनटाइम, इन्हें सेव और बाइंड करता है. इसलिए, आपका एक्सटेंशन कोड, process.env.PARAM_NAME को सीधे पढ़ सकता है. Cloud Functions के सामान्य 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. 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 के पिछले वर्शन के लिए, एक्सटेंशन को उसी एक्सटेंशन में टास्क क्यू फ़ंक्शन को टारगेट करने के लिए, अपने एक्सटेंशन इंस्टेंस आईडी को दूसरे पैरामीटर के तौर पर पास करना पड़ता था. `firebase-admin` 14.2.0 से, इसकी ज़रूरत नहीं है. साथ ही, हमारा सुझाव है कि इसका इस्तेमाल न करें. Task Queue API अब डिफ़ॉल्ट रूप से, एक ही कॉन्टेक्स्ट (जैसे, एक्सटेंशन) में टास्क क्यू को टारगेट करेगा. अपने कोड में, इस पैरामीटर को एक्सटेंशन और स्टैंडअलोन फ़ंक्शन, दोनों के तौर पर हटाया जा सकता है. हमारा सुझाव है कि इसे हटा दें. इस पैरामीटर को हटाने से, पोर्टेबिलिटी और फ़ॉरवर्ड कंपैटिबिलिटी पक्की होती है.

enqueue कॉल के बारे में बाकी सभी जानकारी — the locations/region/functions/name रिसॉर्स पाथ, the task पेलोड, और फिर से कोशिश करने का लॉजिक — पहले जैसा ही रहता है.

Cloud Tasks की मदद से, फ़ंक्शन को क्यू में जोड़ने के बारे में ज़्यादा जानकारी के लिए, /docs/functions/task-functions देखें.Cloud Tasks

इससे पहले. 1st gen एक्सटेंशन

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);

इसके बाद. 2nd gen एक्सटेंशन

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.

ज़रूरी एपीआई और IAM रोल का एलान करना

अपने एक्सटेंशन के IAM और एपीआई की ज़रूरी शर्तों को 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 में एलान किया गया. Extensions रनटाइम ने एपीआई को चालू किया और मैनेज किए गए खाते को रोल असाइन किए:

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. ऐसा इसलिए, क्योंकि सामान्य तौर पर डिप्लॉय किए गए 2nd gen फ़ंक्शन से कॉल करने पर, इनमें गड़बड़ी होगी. लाइफ़साइकल स्टेट अब 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

इससे पहले. extension.yaml में lifecycleEvents, जिसे 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(...) की मदद से करता है.

  • वे Google API जिन्हें पैकेज चालू करता है या जिनकी उसे ज़रूरत होती है.

  • वे लाइफ़साइकल हुक जिनका एलान पैकेज करता है. साथ ही, उन्हें मैन्युअल तौर पर फिर से चलाने का तरीका.

  • बिलिंग से जुड़ी जानकारी.

  • मूल एक्सटेंशन की तुलना में क्या बदला है.

काम करने का उदाहरण: Stream Firestore to BigQuery

पैकेज के README में, "क्या बदला" टेबल शामिल होती है:

चिंता एक्सटेंशन के तौर पर @firebase/firestore-bigquery-export के तौर पर
कॉन्फ़िगरेशन एक्सटेंशन पैरामीटर .env के ज़रिए फ़ंक्शन पैरामीटर
IAM Extensions ने अनुमति दी requiresRole(...), डिप्लॉयमेंट के समय लागू किया गया
प्रोविज़निंग Extensions से लाइफ़साइकल टास्क afterFirstDeploy / afterRedeploy टास्क
फ़ंक्शन के नाम ext-instanceId-fsexportbigquery fsexportbigquery (ज़रूरत के हिसाब से प्रीफ़िक्स जोड़ा जा सकता है)

अपने 2nd gen फ़ंक्शन की जांच करना

अब आपके पास 2nd gen फ़ंक्शन होना चाहिए. डिप्लॉय करने पर, यह आपके एक्सटेंशन के नए इंस्टॉलेशन की तरह ही काम करेगा. आखिरी चरण में, रास्ते में हुई किसी भी गड़बड़ी की पुष्टि करें और उसे ठीक करें.

पक्का करें कि आपने firebase-tools >= 15.24.0 का इस्तेमाल किया हो. साथ ही, अपने बदले गए 2nd gen फ़ंक्शन को टेस्ट प्रोजेक्ट में डिप्लॉय करें. इसमें, उसके व्यवहार की जांच करने के लिए सही संसाधन शामिल होने चाहिए. अगर आपने अपने एक्सटेंशन की जांच करने के लिए पहले से ही कोई टेस्ट प्रोजेक्ट सेटअप किया है, तो यह कमांड इस्तेमाल करें:

firebase deploy --only functions

यह कमांड डालने के बाद, दिखने वाले विज़र्ड में पैरामीटर की वैल्यू डालें. ठीक उसी तरह जैसे आपने एक्सटेंशन के लिए, Firebase कंसोल में इंस्टॉलेशन फ़ॉर्म भरा था.

काम करने का उदाहरण: Stream Firestore to BigQuery

हम Cloud Firestore से BigQuery सिंक की एंड-टू-एंड पुष्टि करते हैं:

  1. अगर Cloud Firestore कंसोल में, COLLECTION_PATH (users) के तौर पर सेट किया गया कलेक्शन पहले से मौजूद नहीं है, तो उसे बनाएं.
  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. Cloud Firestore में, bigquery-mirror-test दस्तावेज़ मिटाएं. यह नए व्यू से गायब हो जाता है. साथ ही, रॉ चेंजलॉग टेबल में DELETE इवेंट जुड़ जाता है.

किसी एक दस्तावेज़ का पूरा इतिहास देखने के लिए, यह कमांड इस्तेमाल करें:

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

एक्सटेंशन की जांच करने से जुड़े अंतर:

  • ट्रिगर, ext-&lt;instanceId&gt;-fsexportbigquery के तौर पर नहीं, बल्कि fsexportbigquery (ज़रूरत के हिसाब से कोडबेस-प्रीफ़िक्स जोड़ा जा सकता है) के तौर पर डिप्लॉय होता है. Cloud Functions डैशबोर्ड और लॉग में, उस नाम को देखें.
  • आपका कोड अब Firebase Local Emulator Suite में, सामान्य फ़ंक्शन के तौर पर चलेगा. एम्युलेटर में इस्तेमाल किए जाने वाले पैरामीटर की वैल्यू, .env.local की मदद से सेट की जा सकती है. firebase-functions-test SDK टूल का इस्तेमाल करके, अपने कोड की यूनिट जांच भी की जा सकती है. इसके बारे में, Unit testing of Cloud Functions लेख में बताया गया है
  • प्रोविज़निंग अब Extensions रनटाइम से नहीं चलाया जाता. अगर डिप्लॉय करने के बाद, चेंजलॉग टेबल मौजूद नहीं है, तो सेटअप टास्क को मैन्युअल तौर पर फिर से चलाएं: firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME. टास्क आइडमपोटेंट है. इसलिए, इसे फिर से चलाने पर डेटासेट, टेबल, और व्यू को फिर से बनाया जाता है.
  • पैरामीटर की वैल्यू, इंस्टॉलेशन फ़ॉर्म के बजाय .env से मिलती हैं. इसलिए, .env पूरा होने के बाद, firebase deploy को फिर से चलाने पर कोई इंटरैक्शन नहीं होता.