दस्तावेज़ पर जाएँ
Ruby

पुनः प्रयास और idempotency

क्या retry होता है, क्या जानबूझकर नहीं, और क्यों retry किया गया send दोहरा नहीं सकता।

भेजना

क्लाइंट हर send (emails.send, emails.send_batch, templates.send और broadcasts.send) पर एक Idempotency-Key जोड़ता है, जो प्रति **कॉल** एक बार oe- और एक रैंडम UUID के रूप में बनती है, और उस कॉल के पुनः प्रयास उसी को दोबारा इस्तेमाल करते हैं। API कुछ भी भेजने से पहले उस कुंजी पर दावा कर लेता है, इसलिए पुनः प्रयास दूसरा संदेश भेजने के बजाय मूल संदेश को replay करता है, जबकि जानबूझकर की गई दो send कॉल फिर भी दो बार भेजती हैं। ये अलग इरादे हैं और अलग ही रहते हैं।

इस गारंटी को प्रोसेस के पार ले जाने के लिए अपनी idempotency_key: पास करें, ताकि जो जॉब क्रैश होकर दोबारा चला वह अपने sends दोहराने के बजाय उन्हें replay करे। replay replayed को true रखकर और सहेजे गए संदेश को उसकी मौजूदा स्थिति में लौटाकर जवाब देता है।

idempotency.rb
invoice_id = "inv_2026_09_4192" sent = client.emails.send(  from: "[email protected]",  to: "[email protected]",  subject: "Your September invoice",  text: "Invoice attached.",  idempotency_key: "invoice:#{invoice_id}") puts sent[:id], sent[:replayed]

इसे उस चीज़ से निकालें जिसने send को ज़रूरी बनाया। घड़ी से कभी नहीं। किसी कुंजी को अलग बॉडी के साथ दोबारा इस्तेमाल करने पर चुपचाप replay होने के बजाय 422 idempotency_key_reuse के साथ अस्वीकार किया जाता है। कुंजी अक्षरों, अंकों, _, ., : या - के 1 से 255 वर्णों की होती है, और इसके अलावा कुछ भी 400 invalid_idempotency_key है।

बाकी सब

हर GET पर पुनः प्रयास होता है। किसी write पर पुनः प्रयास केवल तभी होता है जब दूसरी हूबहू वही रिक्वेस्ट पहली से कुछ अलग मायने रख ही न सके, और send इस कसौटी पर खरा उतरता है क्योंकि उसकी idempotency कुंजी दोहराव को replay में बदल देती है।

कॉलपुनः प्रयासक्यों
हर GETहाँकुछ नहीं बदलता।
emails.send, emails.send_batch, templates.send, broadcasts.sendहाँidempotency key दोहराव को replay बना देती है।
emails.cancel, emails.reschedule, broadcasts.cancel, forms.pause, forms.resume, threads.restoreहाँकिसी नामित स्थिति का शुद्ध सेट।
threads.update, threads.trashहाँलेबल का सेट। उसे दो बार लगाना एक बार लगाना ही है।
threads.snooze, threads.unsnoozeहाँजागने का क्षण body में होता है, आगमन के समय से नहीं निकाला जाता।
emails.update, labels.update, webhooks.update, settings.update, roles.update, members.update, domains.update, domains.update_address, domains.update_address_forward, contacts.update, audiences.update, keys.update, forms.update, branding.update, threads.update_note, chats.rename, account.set_email_notification, account.set_push_muted, app_host.set, workspaces.set_activeहाँनामित फ़ील्ड का शुद्ध सेट।
members.grant_address, members.grant_domain, rules.reorder, threads.reorder_notesहाँgrant एक upsert है, और क्रम पूरा का पूरा बताया जाता है।
templates.publish, forms.publish, imports.startहाँपहले से प्रकाशित चीज़ को प्रकाशित करने पर, या पहले से शुरू हो चुके import को शुरू करने पर, वह अपरिवर्तित लौटता है।
templates.preview, templates.render, broadcasts.preview, rules.testहाँये render करते हैं, गिनते हैं या मूल्यांकन करते हैं, लिखते कुछ नहीं।
domains.verify, app_host.verify, senders.researchहाँदोहराई गई जाँच उसके किए जाने के समय के सिवा कुछ नहीं बदलती।
contacts.save, contacts.set_audiences, contacts.remove_photo, contacts.block, contacts.unblock, contacts.delete_many, keys.revoke, files.revoke_link, files.revoke_all_links, app_host.delete, account.remove_photo, branding.remove_image, domains.remove_logo, domains.remove_logo_certificate, domains.remove_address_photo, account.accept_invitation, account.decline_invitation, forms.approve_submission, subscriptions.moveहाँहर एक अंतिम परिणाम बताता है, इसलिए दूसरा कॉल वही छोड़ता है जो पहले ने छोड़ा था।
audiences.add_contact, audiences.add_contacts, audiences.remove_contacts, audiences.import_contacts, suppressions.add, domains.create_addressहाँदोहराव पहले कॉल का काम पहले से हुआ पाता है और उसे दो बार करने के बजाय उसकी सूचना देता है।
contacts.set_photo, account.set_photo, branding.upload_image, domains.set_logo, domains.set_logo_certificate, domains.set_address_photo, imports.upload_chunkहाँदोबारा भेजे गए बाइट्स वह बदल देते हैं जो पहली कोशिश ने संग्रहीत किया था।
drafts.create, labels.create, webhooks.create, templates.create, rules.create, roles.create, temp_mail.create, files.uploadनहींretry दो object छोड़ जाता है।
drafts.updateनहींजो id आपने भेजी थी उसे दोबारा इस्तेमाल करने के बजाय हर write के परिणाम से id पढ़ें।
drafts.delete, labels.delete, webhooks.delete, templates.delete, rules.delete, roles.delete, members.remove, members.revoke_address, temp_mail.delete, temp_mail.delete_messageनहींरिस्पॉन्स खो जाने के बाद किया गया retry उस काम को विफल बताता है जो सफल हो चुका था।
webhooks.rotate_secretनहींदूसरा rotation उस secret को रद्द कर देता है जो पहली कोशिश ने लौटाया था।
webhooks.testनहींयह दूसरी बनावटी delivery भेज देता।
webhooks.replay_deliveryनहींयह event को आपके receiver को दूसरी बार भेज देता।
emails.translate, emails.compose, emails.rewrite, emails.suggest_subjectनहींहर एक मॉडल कॉल ख़र्च करता है, इसलिए बिना जवाब वाली रिक्वेस्ट के बाद किया गया पुनः प्रयास वही जवाब दो बार ख़रीदता है।
security.begin_step_up, security.verify_step_upनहींपुनः प्रयास दूसरा ईमेल भेज सकता है या कोड पर दूसरी कोशिश ख़र्च कर सकता है।
हर दूसरी कॉल जो GET नहीं हैनहींएक ही बार भेजा जाता है, और विफलता दोहराई नहीं बल्कि बताई जाती है।

बैकऑफ़

  • क्लाइंट पर max_retries: से सीमित, डिफ़ॉल्ट रूप से दो अतिरिक्त प्रयास। max_retries: 0 पुनः प्रयास बंद कर देता है।
  • केवल नेटवर्क विफलता या 408, 500, 502, 503 या 504 के बाद। 429 पर पुनः प्रयास तभी होता है जब वह Retry-After लिए आए, और यह API उसे नहीं भेजता, इसलिए rate limit सीधे raise होता है। कोई भी दूसरा status तुरंत raise होता है।
  • आधे सेकंड से आठ सेकंड तक घातांकी, jitter के साथ: हर इंतज़ार उस ऊपरी सीमा के आधे और पूरे के बीच का कोई रैंडम बिंदु होता है, ताकि बहाली के समय क्लाइंटों का पूरा बेड़ा फिर से एक साथ न चल पड़े।
  • Retry-After की गति से, उसके दोनों रूपों में: delay-seconds और HTTP-date। जब सर्वर प्रतीक्षा बताता है, तो क्लाइंट backoff करने के बजाय ठीक उतनी ही देर रुकता है।
  • एक मिनट से ज़्यादा माँगने वाले सर्वर को क्लाइंट से सोने को नहीं, रुक जाने को कहना माना जाता है, इसलिए error retry_after_seconds के साथ raise होती है। उसके माँगे से जल्दी लौटना उसका पालन नहीं है।
  • टाइमआउट भी किसी दूसरी नेटवर्क विफलता जैसा ही है, इसलिए दोहराने में सुरक्षित कॉल उसके बाद फिर आज़माई जाती है, और timeout: हर प्रयास पर नए सिरे से लागू होता है।
  • ये इंतज़ार कॉल के अंदर sleep कॉल होते हैं, इसलिए कॉल करने वाला थ्रेड भी इंतज़ार करता है, और कॉल तभी लौटती है या raise करती है जब उसका आख़िरी प्रयास ख़त्म हो जाए।