एसिंक्रोनस फ़ंक्शन को फिर से आज़माएं

इस दस्तावेज़ में बताया गया है कि असिंक्रोनस (नॉन-एचटीटीपीएस) बैकग्राउंड फ़ंक्शन के लिए, गड़बड़ी होने पर फिर से कोशिश करने का अनुरोध कैसे किया जा सकता है.

इवेंट ट्रिगर होने पर चलने वाले फ़ंक्शन पूरे क्यों नहीं होते

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

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

  • फ़ंक्शन में कोई गड़बड़ी है और रनटाइम में कोई अपवाद दिखता है.
  • फ़ंक्शन, किसी सेवा के एंडपॉइंट तक नहीं पहुंच सकता या ऐसा करने की कोशिश करते समय उसका समय खत्म हो जाता है.
  • फ़ंक्शन जान-बूझकर अपवाद दिखाता है. उदाहरण के लिए, जब कोई पैरामीटर मान्य नहीं होता.
  • Node.js फ़ंक्शन, अस्वीकार किया गया प्रॉमिस दिखाता है या कॉलबैक को null के अलावा कोई दूसरी वैल्यू पास करता है.

ऊपर दिए गए किसी भी मामले में, फ़ंक्शन काम करना बंद कर देगा और गड़बड़ी का मैसेज दिखाएगा. मैसेज जनरेट करने वाले इवेंट ट्रिगर में फिर से कोशिश करने की नीतियां होती हैं. इन्हें अपने फ़ंक्शन की ज़रूरतों के हिसाब से बदला जा सकता है.

फिर से कोशिश करने के सिमैंटिक

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

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

अपने फ़ंक्शन कोड से फिर से कोशिश करने की सुविधा कॉन्फ़िगर करना

Cloud Functions for Firebase की मदद से, किसी फ़ंक्शन के लिए कोड में फिर से कोशिश करने की सुविधा चालू की जा सकती है. अगर आपको बैकग्राउंड में होने वाले किसी इवेंट के लिए ऐसा करना है, जैसे कि नया Firestore दस्तावेज़ बनाना, तो failurePolicy (1st gen) या retry नीति (2nd gen) विकल्प को true पर सेट करें:

1st gen

exports.docCreated = functions
  .runWith({
    // retry on failure
    failurePolicy: true,
  })
  .firestore.document("my-collection/{docId}")
  .onCreate((change, context) => {
    /* ... */
  });

2nd gen

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

exports.docCreated = onDocumentCreated(
  {
    // retry on failure
    retry: true,
  },
  "my-collection/{docId}",
  (event) => {
    /* ... */
  },
);

यहां दिखाए गए तरीके से true को सेट करने पर, फ़ंक्शन को फिर से कोशिश करने के लिए कॉन्फ़िगर किया जाता है.

फिर से कोशिश करने की विंडो

दूसरी जनरेशन के फ़ंक्शन के लिए, फिर से कोशिश करने की यह विंडो 24 घंटे बाद बंद हो जाती है. पहली जनरेशन के फ़ंक्शन के लिए, इसकी समयसीमा सात दिनों के बाद खत्म हो जाती है. Cloud Functions इवेंट ट्रिगर होने पर काम करने वाले नए फ़ंक्शन को फिर से ट्रिगर करने की कोशिश करता है. इसके लिए, वह एक्सपोनेंशियल बैकऑफ़ रणनीति का इस्तेमाल करता है. इसमें बैकऑफ़ का समय 10 से 600 सेकंड के बीच होता है. यह नीति, नए फ़ंक्शन को पहली बार डिप्लॉय करने पर लागू होती है. यह उन मौजूदा फ़ंक्शन पर लागू नहीं होता जिन्हें इस रिलीज़ नोट में बताए गए बदलावों के लागू होने से पहले डिप्लॉय किया गया था. भले ही, आपने फ़ंक्शन को फिर से डिप्लॉय किया हो.

सबसे सही तरीके

इस सेक्शन में, फिर से कोशिश करने की सुविधा इस्तेमाल करने के सबसे सही तरीके बताए गए हैं.

कुछ समय के लिए होने वाली गड़बड़ियों को ठीक करने के लिए, फिर से कोशिश करने की सुविधा का इस्तेमाल करना

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

अनंत बार फिर से कोशिश करने वाले लूप से बचने के लिए, खत्म होने की शर्त सेट करें

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

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

उदाहरण के लिए, यह कोड स्निपेट 10 सेकंड से पुराने सभी इवेंट को खारिज कर देता है:

const eventAgeMs = Date.now() - Date.parse(event.timestamp);
const eventMaxAgeMs = 10000;
if (eventAgeMs > eventMaxAgeMs) {
  console.log(`Dropping event ${event} with age[ms]: ${eventAgeMs}`);
  callback();
  return;
}

प्रॉमिस के साथ catch का इस्तेमाल करना

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

यहां एक उदाहरण दिया गया है कि आपको क्या करना चाहिए:

return doFooAsync().catch((err) => {
    if (isFatal(err)) {
        console.error(`Fatal error ${err}`);
    }
    return Promise.reject(err);
});

इवेंट-ड्रिवन फ़ंक्शन को फिर से ट्रिगर करने की सुविधा के साथ आइडमपोटेंट बनाना

इवेंट पर आधारित ऐसे फ़ंक्शन जिन्हें फिर से आज़माया जा सकता है, वे आइडेमपोटेंट होने चाहिए. यहां ऐसे फ़ंक्शन को आइडमपोटेंट बनाने के लिए कुछ सामान्य दिशा-निर्देश दिए गए हैं:

  • कई बाहरी एपीआई (जैसे, Stripe) आपको पैरामीटर के तौर पर, idempotency key देने की सुविधा देते हैं. अगर ऐसे एपीआई का इस्तेमाल किया जा रहा है, तो आपको इवेंट आईडी को आईडम्पोटेंसी कुंजी के तौर पर इस्तेमाल करना चाहिए.
  • आइटम को कम से कम एक बार डिलीवर करने की सुविधा के साथ, आइटम को एक बार से ज़्यादा प्रोसेस न करने की सुविधा अच्छी तरह से काम करती है. ऐसा इसलिए, क्योंकि इससे अनुरोध को फिर से भेजने का विकल्प सुरक्षित हो जाता है. इसलिए, भरोसेमंद कोड लिखने का सबसे सही तरीका यह है कि आप रीट्राय करने की सुविधा के साथ-साथ, आइडेंपोटेंसी का इस्तेमाल करें.
  • पक्का करें कि आपका कोड, इंटरनल तौर पर आइडमपोटेंट हो. उदाहरण के लिए:
    • पक्का करें कि नतीजे में बदलाव किए बिना, म्यूटेशन एक से ज़्यादा बार हो सकते हैं.
    • स्टेट में बदलाव करने से पहले, लेन-देन में डेटाबेस की स्थिति के बारे में क्वेरी करें.
    • पक्का करें कि सभी साइड इफ़ेक्ट, खुद से आइडेमपोटेंट हों.
  • फ़ंक्शन के बाहर लेन-देन की जांच करें. यह जांच कोड से अलग होनी चाहिए. उदाहरण के लिए, किसी ऐसी जगह पर स्थिति को सेव करें जहां यह रिकॉर्ड किया गया हो कि दिए गए इवेंट आईडी को पहले ही प्रोसेस किया जा चुका है.
  • डुप्लीकेट फ़ंक्शन कॉल को आउट-ऑफ़-बैंड तरीके से मैनेज करें. उदाहरण के लिए, एक अलग क्लीन अप प्रोसेस बनाएं. यह प्रोसेस, फ़ंक्शन को डुप्लीकेट कॉल करने के बाद क्लीन अप करती है.

फिर से कोशिश करने की नीति को कॉन्फ़िगर करना

अपने फ़ंक्शन की ज़रूरतों के आधार पर, सीधे तौर पर फिर से कोशिश करने की नीति को कॉन्फ़िगर किया जा सकता है. इससे, आपको इनमें से किसी भी कॉम्बिनेशन को सेट अप करने की अनुमति मिलेगी:

  • फिर से कोशिश करने की अवधि को सात दिनों से घटाकर, कम से कम 10 मिनट कर दें.
  • एक्सपोनेंशियल बैकऑफ़ रीट्राय रणनीति के लिए, कम से कम और ज़्यादा से ज़्यादा बैकऑफ़ समय बदलें.
  • फिर से कोशिश करने की रणनीति को बदलकर, तुरंत फिर से कोशिश करने की रणनीति पर सेट करें.
  • डेड-लेटर विषय को कॉन्फ़िगर करें.
  • डिलीवरी की कोशिशों की ज़्यादा से ज़्यादा और कम से कम संख्या सेट करें.

फिर से कोशिश करने की नीति को कॉन्फ़िगर करने के लिए:

  1. एचटीटीपी फ़ंक्शन लिखें.
  2. Pub/Sub सदस्यता बनाने के लिए, Pub/Sub एपीआई का इस्तेमाल करें. साथ ही, फ़ंक्शन के यूआरएल को टारगेट के तौर पर सेट करें.

Pub/Sub को सीधे तौर पर कॉन्फ़िगर करने के बारे में ज़्यादा जानने के लिए, Pub/Sub से जुड़ी गड़बड़ियों को ठीक करने के बारे में दस्तावेज़ देखें.