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

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

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

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

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

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

फिर से कोशिश करने की समयसीमा

2nd gen फ़ंक्शन के लिए, फिर से कोशिश करने की यह समयसीमा 24 घंटे बाद खत्म हो जाती है. 1st gen फ़ंक्शन के लिए, यह समयसीमा सात दिनों के बाद खत्म हो जाती है. 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) आपको आइडेमपोटेंसी की के तौर पर, पैरामीटर उपलब्ध कराने की सुविधा देते हैं. अगर ऐसे किसी एपीआई का इस्तेमाल किया जा रहा है, तो आपको इवेंट आईडी को आइडेमपोटेंसी की के तौर पर इस्तेमाल करना चाहिए.
  • आइडेमपोटेंसी, कम से कम एक बार डिलीवरी की सुविधा के साथ अच्छी तरह से काम करती है, क्योंकि इससे फिर से कोशिश करना सुरक्षित हो जाता है. इसलिए, भरोसेमंद कोड लिखने के लिए, आइडेमपोटेंसी को फिर से कोशिश करने की सुविधा के साथ जोड़ना एक सामान्य सबसे सही तरीका है.
  • पक्का करें कि आपका कोड, इंटरनल तौर पर आइडेमपोटेंट हो. उदाहरण के लिए:
    • पक्का करें कि नतीजे में बदलाव किए बिना, म्यूटेशन एक से ज़्यादा बार हो सकें.
    • स्टेट में बदलाव करने से पहले, किसी ट्रांज़ैक्शन में डेटाबेस की स्थिति के बारे में क्वेरी करें.
    • पक्का करें कि सभी साइड इफ़ेक्ट, खुद आइडेमपोटेंट हों.
  • कोड से अलग, फ़ंक्शन के बाहर ट्रांज़ैक्शनल चेक लागू करें. उदाहरण के लिए, किसी जगह पर स्टेट को सेव करें. इससे यह रिकॉर्ड किया जा सके कि किसी इवेंट आईडी को पहले ही प्रोसेस किया जा चुका है.
  • फ़ंक्शन कॉल की डुप्लीकेट कॉपी को, आउट-ऑफ़-बैंड तरीके से हैंडल करें. उदाहरण के लिए, एक अलग क्लीन अप प्रोसेस बनाएं. यह प्रोसेस, फ़ंक्शन कॉल की डुप्लीकेट कॉपी को हटाने के बाद, क्लीन अप करती है.

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

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

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

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

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

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