पुनः प्रयास और idempotency
क्या retry होता है, क्या जानबूझकर नहीं, और क्यों retry किया गया send दोहरा नहीं सकता।
भेजना
क्लाइंट हर send (emails.send, emails.sendBatch और templates.send) पर एक Idempotency-Key जोड़ता है, जो प्रति **कॉल** एक बार बनती है और उस कॉल के retry उसी को दोबारा इस्तेमाल करते हैं। API कुछ भी भेजने से पहले उस key पर दावा कर लेता है, इसलिए retry दूसरा संदेश भेजने के बजाय मूल संदेश को दोहराता है, जबकि जानबूझकर किए गए दो send() कॉल फिर भी दो बार भेजते हैं। ये अलग इरादे हैं और अलग ही रहते हैं।
अपनी idempotencyKey देकर उस गारंटी को प्रक्रियाओं के पार खींचें, ताकि जो job क्रैश होकर दोबारा चली, वह अपने send दोहराने के बजाय उन्हें replay करे।
await openemail.emails.send(message, { idempotencyKey: `invoice:${invoice.id}` })इसे उसी चीज़ से निकालें जिसने send को ज़रूरी बनाया। घड़ी से कभी नहीं। अलग body के साथ वही key दोबारा इस्तेमाल करना चुपचाप replay होने के बजाय idempotency_key_reuse के साथ अस्वीकार होता है।
बाकी सब
हर read retry होता है। कोई write केवल तभी retry होता है जब दूसरा हूबहू वही request पहले से कुछ अलग मायने रख ही न सके, और send इस कसौटी पर खरा उतरता है क्योंकि उसकी idempotency key दोहराव को replay में बदल देती है।
| कॉल | पुनः प्रयास | क्यों |
|---|---|---|
| हर read | हाँ | कुछ नहीं बदलता। |
| `emails.send`, `emails.sendBatch`, `templates.send` | हाँ | idempotency key दोहराव को replay बना देती है। |
| `emails.cancel`, `emails.reschedule` | हाँ | किसी नामित स्थिति का शुद्ध सेट। |
| `threads.update`, `threads.trash` | हाँ | लेबल का सेट। उसे दो बार लगाना एक बार लगाना ही है। |
| `threads.snooze`, `threads.unsnooze` | हाँ | जागने का क्षण body में होता है, आगमन के समय से नहीं निकाला जाता। |
| `labels.update`, `webhooks.update`, `settings.update`, `roles.update`, `members.update` | हाँ | नामित फ़ील्ड का शुद्ध सेट। |
| `members.grantAddress`, `rules.reorder` | हाँ | grant एक upsert है, और क्रम पूरा का पूरा बताया जाता है। |
| `templates.publish` | हाँ | पहले से प्रकाशित head को प्रकाशित करने पर वह अपरिवर्तित लौटता है। |
| `templates.preview`, `rules.test` | हाँ | ये render या मूल्यांकन करते हैं, लिखते कुछ नहीं। |
| `drafts.create`, `labels.create`, `webhooks.create`, `templates.create`, `rules.create`, `roles.create`, `tempMail.create` | नहीं | retry दो object छोड़ जाता है। |
| `drafts.update` | नहीं | जो id आपने भेजी थी उसे दोबारा इस्तेमाल करने के बजाय हर write के परिणाम से id पढ़ें। |
| `drafts.delete`, `labels.delete`, `webhooks.delete`, `templates.delete`, `rules.delete`, `roles.delete`, `members.remove`, `members.revokeAddress`, `tempMail.delete`, `tempMail.deleteMessage` | नहीं | रिस्पॉन्स खो जाने के बाद किया गया retry उस काम को विफल बताता है जो सफल हो चुका था। |
| `webhooks.rotateSecret` | नहीं | दूसरा rotation उस secret को रद्द कर देता है जो पहली कोशिश ने लौटाया था। |
| `webhooks.test` | नहीं | यह दूसरी बनावटी delivery भेज देता। |
| `emails.translate` | नहीं | यह मॉडल कॉल खर्च करता है, इसलिए बिना उत्तर वाले request के बाद किया गया retry वही उत्तर दो बार खरीदता है। |
| हर दूसरा write | नहीं | एक ही बार भेजा जाता है, और विफलता दोहराई नहीं बल्कि बताई जाती है। |
बैकऑफ़
- क्लाइंट पर
maxRetriesसे सीमित, जिसका डिफ़ॉल्ट दो अतिरिक्त कोशिशें हैं। - केवल नेटवर्क विफलता या
408,500,502,503या504के बाद।429तभी retry होता है जब वहRetry-Afterलिए आए, और यह API उसे नहीं भेजता, इसलिए rate limit सीधे throw करता है। कोई भी दूसरा status तुरंत throw करता है। - आधे सेकंड से आठ सेकंड तक घातीय, jitter के साथ, ताकि रिकवरी पर पूरा बेड़ा फिर से एक साथ न आ जाए।
Retry-Afterकी गति से, उसके दोनों रूपों में — delay-seconds और HTTP-date। जब सर्वर प्रतीक्षा बताता है, तो क्लाइंट backoff करने के बजाय ठीक उतनी ही देर रुकता है।- एक मिनट से ज़्यादा माँगने वाले सर्वर को क्लाइंट से सोने को नहीं, रुक जाने को कहना माना जाता है, इसलिए error उस पर
retryAfterSecondsके साथ उठाई जाती है। उसके माँगे से जल्दी लौटना उसका पालन नहीं है। - कॉल करने वाले का
AbortSignalकभी retry नहीं होता। abort तुरंतOpenEmailNetworkErrorthrow करता है, चाहे request से या अगली कोशिश से पहले की प्रतीक्षा से।