1st gen Node.js फ़ंक्शन को 2nd gen पर अपग्रेड करें

फ़िलहाल, पहले जनरेशन के फ़ंक्शन का इस्तेमाल करने वाले ऐप्लिकेशन को इस गाइड में दिए गए निर्देशों का इस्तेमाल करके, दूसरे जनरेशन पर माइग्रेट करना चाहिए. दूसरे जनरेशन के फ़ंक्शन, बेहतर परफ़ॉर्मेंस, बेहतर कॉन्फ़िगरेशन, बेहतर मॉनिटरिंग वगैरह देने के लिए, Cloud Run का इस्तेमाल करते हैं.

इस पेज पर दिए गए उदाहरणों में यह माना गया है कि CommonJS मॉड्यूल (require स्टाइल इंपोर्ट) के साथ JavaScript का इस्तेमाल किया जा रहा है. हालांकि, ये सिद्धांत ESM (import … from स्टाइल इंपोर्ट) और TypeScript के साथ JavaScript पर भी लागू होते हैं.

माइग्रेशन की प्रोसेस

पहले और दूसरे जनरेशन के फ़ंक्शन, एक ही फ़ाइल में एक साथ काम कर सकते हैं. इससे, आपके पास धीरे-धीरे माइग्रेट करने का विकल्प होता है. हमारा सुझाव है कि एक बार में एक फ़ंक्शन को माइग्रेट करें. साथ ही, आगे बढ़ने से पहले, उसकी जांच और पुष्टि करें.

Firebase CLI और firebase-function के वर्शन की पुष्टि करना

पक्का करें कि आपने Firebase CLI के कम से कम 12.00 वर्शन और firebase-functions के 4.3.0 वर्शन का इस्तेमाल किया हो. नया वर्शन, पहले और दूसरे जनरेशन, दोनों के साथ काम करेगा.

इंपोर्ट अपडेट करना

दूसरे जनरेशन के फ़ंक्शन, firebase-functions SDK में मौजूद v2 सब-पैकेज से इंपोर्ट होते हैं. Firebase CLI को यह तय करने के लिए, इंपोर्ट के इस अलग पाथ की ज़रूरत होती है कि आपके फ़ंक्शन कोड को पहले या दूसरे जनरेशन के फ़ंक्शन के तौर पर डिप्लॉय किया जाए.

v2 सब-पैकेज मॉड्यूलर है. हमारा सुझाव है कि सिर्फ़ उस मॉड्यूल को इंपोर्ट करें जिसकी आपको ज़रूरत है.

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

const functions = require("firebase-functions/v1");

इसके बाद: 2nd gen

// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

ट्रिगर की परिभाषाएं अपडेट करना

दूसरे जनरेशन का SDK टूल, मॉड्यूलर इंपोर्ट का इस्तेमाल करता है. इसलिए, पिछले चरण में किए गए बदलावों को दिखाने के लिए, ट्रिगर की परिभाषाएं अपडेट करें.

कुछ ट्रिगर के लिए कॉलबैक में पास किए गए आर्ग्युमेंट बदल गए हैं. इस उदाहरण में, ध्यान दें कि onDocumentCreated कॉलबैक के आर्ग्युमेंट को एक event ऑब्जेक्ट में इकट्ठा किया गया है. इसके अलावा, कुछ ट्रिगर में कॉन्फ़िगरेशन की सुविधाएं भी नई और आसान हैं. जैसे, onRequest ट्रिगर का cors विकल्प.

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

const functions = require("firebase-functions/v1");

exports.date = functions.https.onRequest((req, res) => {
  // ...
});

exports.uppercase = functions.firestore
  .document("my-collection/{docId}")
  .onCreate((change, context) => {
    // ...
  });

इसके बाद: 2nd gen

const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

exports.date = onRequest({cors: true}, (req, res) => {
  // ...
});

exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
  /* ... */
});

पैरामीटर वाले कॉन्फ़िगरेशन का इस्तेमाल करना

दूसरे जनरेशन के फ़ंक्शन, functions.config के साथ काम नहीं करते. ऐसा इसलिए किया गया है, ताकि आपके कोडबेस में कॉन्फ़िगरेशन पैरामीटर को साफ़ तौर पर तय करने के लिए, ज़्यादा सुरक्षित इंटरफ़ेस का इस्तेमाल किया जा सके. नए params मॉड्यूल के साथ, सीएलआई तब तक डिप्लॉयमेंट को ब्लॉक करता है, जब तक सभी पैरामीटर की मान्य वैल्यू नहीं दी जाती. इससे यह पक्का होता है कि किसी फ़ंक्शन को बिना कॉन्फ़िगरेशन के डिप्लॉय न किया जाए.

params सब-पैकेज पर माइग्रेट करना

अगर functions.config के साथ एनवायरमेंट कॉन्फ़िगरेशन का इस्तेमाल किया जा रहा है, तो अपने मौजूदा कॉन्फ़िगरेशन को पैरामीटर वाले कॉन्फ़िगरेशन पर माइग्रेट किया जा सकता है.

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

const functions = require("firebase-functions/v1");

exports.date = functions.https.onRequest((req, res) => {
  const date = new Date();
  const formattedDate =
date.toLocaleDateString(functions.config().dateformat);

  // ...
});

इसके बाद: 2nd gen

const {onRequest} = require("firebase-functions/v2/https");
const {defineString} = require("firebase-functions/params");

const dateFormat = defineString("DATE_FORMAT");

exports.date = onRequest((req, res) => {
  const date = new Date();
  const formattedDate = date.toLocaleDateString(dateFormat.value());

  // ...
});

पैरामीटर वैल्यू को सेट करना

पहली बार डिप्लॉय करने पर, Firebase CLI पैरामीटर की सभी वैल्यू के लिए प्रॉम्प्ट करता है और वैल्यू को dotenv फ़ाइल में सेव करता है. अपनी functions.config वैल्यू एक्सपोर्ट करने के लिए, firebase functions:config:export चलाएं.

ज़्यादा सुरक्षा के लिए, पैरामीटर के टाइप और पुष्टि करने के नियम भी तय किए जा सकते हैं.

खास मामला: एपीआई पासकोड

params मॉड्यूल, Cloud Secret Manager के साथ इंटिग्रेट होता है. इससे एपीआई पासकोड जैसी संवेदनशील वैल्यू के लिए, ऐक्सेस कंट्रोल की बेहतर सुविधा मिलती है. ज़्यादा जानकारी के लिए, सीक्रेट पैरामीटर देखें.

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

const functions = require("firebase-functions/v1");

exports.getQuote = functions.https.onRequest(async (req, res) => {
  const quote = await fetchMotivationalQuote(functions.config().apiKey);
  // ...
});

इसके बाद: 2nd gen

const {onRequest} = require("firebase-functions/v2/https");
const {defineSecret} = require("firebase-functions/params");

// Define the secret parameter
const apiKey = defineSecret("API_KEY");

exports.getQuote = onRequest(
  // make the secret available to this function
  { secrets: [apiKey] },
  async (req, res) => {
    // retrieve the value of the secret
    const quote = await fetchMotivationalQuote(apiKey.value());
    // ...
  }
);

रनटाइम के विकल्प सेट करना

पहले और दूसरे जनरेशन के बीच, रनटाइम विकल्पों का कॉन्फ़िगरेशन बदल गया है. दूसरे जनरेशन में, सभी फ़ंक्शन के लिए विकल्प सेट करने की नई सुविधा भी जोड़ी गई है.

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

const functions = require("firebase-functions/v1");

exports.date = functions
  .runWith({
    // Keep 5 instances warm for this latency-critical function
    minInstances: 5,
  })
  // locate function closest to users
  .region("asia-northeast1")
  .https.onRequest((req, res) => {
    // ...
  });

exports.uppercase = functions
  // locate function closest to users and database
  .region("asia-northeast1")
  .firestore.document("my-collection/{docId}")
  .onCreate((change, context) => {
    // ...
  });

इसके बाद: 2nd gen

const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions/v2");

// locate all functions closest to users
setGlobalOptions({ region: "asia-northeast1" });

exports.date = onRequest({
    // Keep 5 instances warm for this latency-critical function
    minInstances: 5,
  }, (req, res) => {
  // ...
});

exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
  /* ... */
});

एक साथ कई टास्क करने की सुविधा का इस्तेमाल करना

दूसरे जनरेशन के फ़ंक्शन का एक अहम फ़ायदा यह है कि एक फ़ंक्शन के एक ही इंस्टेंस से एक से ज़्यादा अनुरोधों को एक साथ पूरा किया जा सकता है. इससे, असली उपयोगकर्ताओं को कोल्ड स्टार्ट की संख्या में काफ़ी कमी आ सकती है. डिफ़ॉल्ट रूप से, एक साथ कई टास्क करने की सीमा 80 पर सेट होती है. हालांकि, इसे 1 से 1,000 तक की किसी भी वैल्यू पर सेट किया जा सकता है:

const {onRequest} = require("firebase-functions/v2/https");

exports.date = onRequest({
    // set concurrency value
    concurrency: 500
  },
  (req, res) => {
    // ...
});

एक साथ कई टास्क करने की सुविधा को ट्यून करने से, परफ़ॉर्मेंस बेहतर हो सकती है और फ़ंक्शन की लागत कम हो सकती है. एक साथ कई अनुरोध करने की अनुमति दें में, एक साथ कई अनुरोध करने की सुविधा के बारे में ज़्यादा जानें.

ग्लोबल वैरिएबल के इस्तेमाल का ऑडिट करना

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

अपग्रेड करते समय, अपने फ़ंक्शन के सीपीयू को gcf_gen1 पर सेट किया जा सकता है. साथ ही, पहले जनरेशन के फ़ंक्शन का व्यवहार वापस पाने के लिए, concurrency को 1 पर सेट किया जा सकता है:

const {onRequest} = require("firebase-functions/v2/https");

exports.date = onRequest({
    // TEMPORARY FIX: remove concurrency
    cpu: "gcf_gen1",
    concurrency: 1
  },
  (req, res) => {
    // ...
});

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

ट्रैफ़िक को दूसरे जनरेशन के नए फ़ंक्शन पर माइग्रेट करना

किसी फ़ंक्शन के क्षेत्र या ट्रिगर टाइप को बदलने की तरह ही, आपको दूसरे जनरेशन के फ़ंक्शन को एक नया नाम देना होगा और धीरे-धीरे उस पर ट्रैफ़िक माइग्रेट करना होगा.

किसी फ़ंक्शन को एक ही नाम से पहले से दूसरे जनरेशन में अपग्रेड नहीं किया जा सकता और firebase deploy को नहीं चलाया जा सकता. ऐसा करने पर, गड़बड़ी का यह मैसेज दिखेगा:

Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.

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

  1. अपने फ़ंक्शन कोड में फ़ंक्शन का नाम बदलें. उदाहरण के लिए, resizeImage का नाम बदलकर resizeImageSecondGen करें.
  2. फ़ंक्शन को डिप्लॉय करें, ताकि ओरिजनल फ़ंक्शन और दूसरे जनरेशन का फ़ंक्शन, दोनों ही चल रहे हों.
    1. कॉल करने लायक, टास्क कतार, और एचटीटीपी ट्रिगर के मामले में, क्लाइंट कोड को दूसरे जनरेशन के फ़ंक्शन के नाम या यूआरएल से अपडेट करके, सभी क्लाइंट को दूसरे जनरेशन के फ़ंक्शन पर ले जाएं.
    2. बैकग्राउंड ट्रिगर की मदद से, पहले और दूसरे जनरेशन, दोनों फ़ंक्शन डिप्लॉय होने के बाद हर इवेंट का तुरंत जवाब देंगे.
  3. जब पूरा ट्रैफ़िक माइग्रेट हो जाए, तो Firebase CLI के firebase functions:delete कमांड का इस्तेमाल करके, पहले जनरेशन का फ़ंक्शन मिटाएं.
    1. इसके अलावा, पहले जनरेशन के फ़ंक्शन के नाम से मैच करने के लिए, दूसरे जनरेशन के फ़ंक्शन का नाम बदला जा सकता है.