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

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

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

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

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

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

Promises के साथ catch का इस्तेमाल करना

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

यहां एक उदाहरण दिया गया है, जिसमें बताया गया है कि आपको क्या करना चाहिए:

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

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

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

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

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

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

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

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

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

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