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

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

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

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

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

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

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

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

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

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

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

Cloud Functions for Firebase की मदद से, किसी फ़ंक्शन के लिए कोड में फिर से कोशिश करने की सुविधा चालू की जा सकती है. अगर आपको बैकग्राउंड में होने वाले किसी इवेंट के लिए ऐसा करना है, जैसे कि नया Firestore दस्तावेज़ बनाना, तो failurePolicy (पहली जनरेशन) या retry (दूसरी जनरेशन) नीति के विकल्प को 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 फ़ेल होने की स्थितियों को मैनेज करने से जुड़ा दस्तावेज़ देखें.