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

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

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

इस गाइड में, Firestore से 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 में एलान किया गया हर पैरामीटर, आपके पैकेज कोड में एक तय पैरामीटर बन जाता है.

  • आईएएम की भूमिकाएं और ज़रूरी एपीआई. extension.yaml में तय की गई हर भूमिका, requiresRole(...) कॉल बन जाती है. साथ ही, हर एपीआई, आपके फ़ंक्शन कोड में requiresAPI(...) कॉल बन जाता है. डप्लॉय करने के समय, Firebase CLI, मैनेज की जा रही रनटाइम सेवा खाते को बताई गई भूमिकाएं असाइन करता है. साथ ही, आपकी ओर से बताए गए एपीआई चालू करता है.

  • Cloud Functions कोडबेस के लिए लाइफ़साइकल इवेंट. Cloud Functions कोडबेस अब Firebase Extensions की तरह ही लाइफ़साइकल इवेंट के साथ काम करते हैं. लाइफ़साइकल हुक afterFirstDeploy(...) और afterRedeploy(...) का इस्तेमाल करके, इंस्टॉल और अपडेट के समय के सेटअप के बारे में बताएं. ये, lifecycleEvents की जगह लेते हैं. extension.yaml में इनका एलान किया जाता है.

Google, firebase-extensions-migrator-support-external@google.com को सूचना देगा.

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

अपने एक्सटेंशन की इन्वेंट्री बनाएं. इसमें एक्सटेंशन के बारे में पूरी जानकारी होनी चाहिए. जैसे, एक्सटेंशन क्या-क्या काम करता है, उसे कैसे शिप किया जाता है, और उसके दस्तावेज़ क्या-क्या हैं. इससे यह पक्का किया जा सकेगा कि 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) में बदलें.

उदाहरण: Firestore से BigQuery में डेटा स्ट्रीम करना

firestore-bigquery-export/extension.yaml और functions/ को पढ़ने पर, यह इन्वेंट्री मिलती है:

extension.yaml फ़ाइल में गिनती / वैल्यू यह कहां दिखता है
params 25 (COLLECTION_PATH, DATASET_ID, TABLE_ID, DATASET_LOCATION, VIEW_TYPE, …) Cloud Functions पैरामीटर (सेक्शन 5)
एपीआई bigquery.googleapis.com requiresAPI(...) (section 7)
भूमिकाएं bigquery.dataEditor, datastore.user, bigquery.user requiresRole(...) (section 7)
संसाधन एक इवेंट ट्रिगर (fsexportbigquery) + टास्क क्यू फ़ंक्शन (initBigQuerySync, setupBigQuerySync) एक्सपोर्ट किए गए पैकेज फ़ंक्शन (तीसरा सेक्शन)
lifecycleEvents onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync afterFirstDeploy / afterRedeploy (section 9)
scripts/ import/ (बैकफ़िल), gen-schema-view/ स्क्रिप्ट के तौर पर सेव किया जाता है (यह यहां के दायरे से बाहर है)

एक्सटेंशन, किसी भी तरह के सीक्रेट पैरामीटर का एलान नहीं करता है. इसलिए, इस गाइड के छठे सेक्शन में माइग्रेट करने के लिए कुछ भी नहीं है. इवेंट ट्रिगर पहले से ही दूसरी जनरेशन का है. सिर्फ़ टास्क क्यू फ़ंक्शन अब भी पहली जनरेशन के हैं (सेक्शन 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 में डेटा स्ट्रीम करना

इससे पहले. एक्सटेंशन के 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 एसडीके अब 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);
  });

इसके बाद. 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);
);
Google, firebase-extensions-migrator-support-external@google.com को सूचना देगा.

पहली जनरेशन और दूसरी जनरेशन के फ़ंक्शन के बीच के अंतर की पूरी सूची देखने के लिए, Cloud Functions वर्शन की तुलना देखें.

एक्सटेंशन पैरामीटर और सीक्रेट को बदलना

पैरामीटर बदलना

extension.yaml में एलान किया गया हर पैरामीटर, Cloud Functions param बन जाता है.

डायरेक्ट एनवायरमेंट रीड को इस तरह से बदलें:

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 से उनकी वैल्यू पढ़ता है. इसके अलावा, यह डिप्लॉयमेंट के दौरान आपके उपयोगकर्ताओं को सूचनाएं भेजता है. पैरामीटर के नाम वही रखें, ताकि मौजूदा इंस्टॉलेशन से वैल्यू ट्रांसफ़र हो सकें.

यह ज़रूरी है कि आप अपने कोड में बताए गए पैरामीटर के नाम बिल्कुल बदलें. एक्सटेंशन माइग्रेशन, असली उपयोगकर्ता के पैरामीटर की मौजूदा वैल्यू को अपने-आप सेव कर लेगा. हालांकि, ऐसा सिर्फ़ तब होगा, जब नाम में कोई बदलाव न किया गया हो.

काम करने का उदाहरण: 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 फ़ाइल में, टाइप: सीक्रेट के साथ सीक्रेट घोषित किए जाते हैं. एक्सटेंशन का रनटाइम, इन एनवायरमेंट वैरिएबल को सेव करता है और उन्हें बाइंड करता है. इसलिए, आपका एक्सटेंशन कोड सीधे तौर पर 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; सीएलआई, दोनों का पता लगाता है और .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 का इस्तेमाल करके, अपने फ़ंक्शन कोड में मौजूद खुद की टास्क कतारों में काम जोड़ते हैं. यह, भेजे गए टास्क को पाने से अलग है. इसके बारे में अपग्रेड फ़ंक्शन और लाइफ़साइकल हुक को बदलना सेक्शन में बताया गया है. यहां आपका कोड, producer है, जो queue.enqueue(...) को कॉल करता है.

Admin SDK के पिछले वर्शन में, एक्सटेंशन को अपने एक्सटेंशन इंस्टेंस आईडी को दूसरे पैरामीटर के तौर पर पास करना होता था, ताकि उसी एक्सटेंशन में टास्क क्यू फ़ंक्शन को टारगेट किया जा सके. `firebase-admin` 14.2.0 से, इसकी ज़रूरत नहीं है और न ही इसे इस्तेमाल करने का सुझाव दिया जाता है. Task Queue API अब डिफ़ॉल्ट रूप से, एक ही कॉन्टेक्स्ट (जैसे, एक्सटेंशन) में मौजूद टास्क कतारों को टारगेट करेगा. इस पैरामीटर को अपने कोड से हटाना सुरक्षित है. साथ ही, हम आपको ऐसा करने का सुझाव देते हैं. इसे एक्सटेंशन और स्टैंडअलोन फ़ंक्शन, दोनों से हटाया जा सकता है. इस पैरामीटर को हटाने से, पोर्टेबिलिटी और फ़ॉरवर्ड कंपैटिबिलिटी पक्का की जा सकती है.

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

const queue = getFunctions().taskQueue(
  `locations/${process.env.FUNCTION_REGION}/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, कोडबेस के लिए मैनेज किया गया रनटाइम सेवा खाता बनाता है या उसे अपडेट करता है. साथ ही, उसे सभी घोषित भूमिकाओं का यूनियन देता है. अपने उपयोगकर्ताओं के लिए एक ऐसा दस्तावेज़ बनाएं जिसमें यह बताया गया हो कि कोडबेस में मौजूद सभी फ़ंक्शन, उन भूमिकाओं के साथ काम करते हैं. हालांकि, अगर फ़ाइनल एपीआई किसी छोटे मॉडल के साथ काम करता है, तो ऐसा नहीं होगा.

उदाहरण: Firestore से BigQuery में डेटा स्ट्रीम करना

इससे पहले. extension.yaml में बताया गया है कि Extensions runtime ने एपीआई चालू किया और मैनेज किए जा रहे खाते को भूमिकाएं असाइन कीं:

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

उदाहरण: Firestore से BigQuery में डेटा स्ट्रीम करना

इससे पहले. lifecycleEvents में extension.yaml, Extensions runtime की मदद से:

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(...) के साथ पैकेज में बताई गई IAM भूमिकाएं.

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

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

  • बिलिंग से जुड़े नोट.

  • ओरिजनल एक्सटेंशन की तुलना में क्या बदला गया है.

उदाहरण: Firestore से BigQuery में डेटा स्ट्रीम करना

पैकेज के README में, "क्या बदला" टेबल की जानकारी दी गई है:

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

अपने 2nd gen फ़ंक्शन को टेस्ट करें

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

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

firebase deploy --only functions

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

उदाहरण: Firestore से 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

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

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