تلاش مجدد و idempotency
چه چیزی دوباره تلاش میشود، چه چیزی عمداً نه، و چرا یک ارسالِ دوبارهتلاششده نمیتواند تکراری شود.
ارسالها
کلاینت به هر ارسال (emails.send، emails.send_batch، templates.send و broadcasts.send) یک Idempotency-Key میچسباند که بهازای هر **فراخوانی** یک بار تولید میشود و همان فراخوانی در تلاشهای مجددش دوباره از آن استفاده میکند. API پیش از آنکه چیزی را روانه کند آن کلید را ثبت میکند، پس یک تلاش مجدد همان پیام اصلی را بازپخش میکند نه اینکه پیام دومی بفرستد، در حالی که دو فراخوانی عمدی send() همچنان دو بار میفرستند. اینها دو نیت متفاوتاند و متفاوت میمانند.
با دادن idempotency_key خودتان، این تضمین را در میان پروسهها گسترش دهید، تا کاری که کرش کرده و دوباره اجرا شده است ارسالهایش را بازپخش کند نه اینکه تکرارشان کند.
invoice_id = 'inv_4192' client.emails.send( {'from': sender, 'to': recipient, 'subject': subject, 'text': text}, idempotency_key=f'invoice:{invoice_id}',)آن را از همان چیزی مشتق کنید که ارسال را لازم کرده است. هرگز از ساعت. استفادهٔ دوباره از یک کلید با بدنهای متفاوت با idempotency_key_reuse رد میشود، نه اینکه بیصدا بازپخش شود.
باقی موارد
هر خواندنی دوباره تلاش میشود. یک نوشتن تنها جایی دوباره تلاش میشود که درخواست دومِ همسان نتواند معنایی متفاوت از اولی داشته باشد، و ارسال واجد شرایط است چون کلید idempotency آن یک تکرار را به بازپخش تبدیل میکند.
| فراخوانی | تلاش مجدد | چرا |
|---|---|---|
| هر خواندن | بله | چیزی تغییر نمیکند. |
| emails.send، emails.send_batch، templates.send، broadcasts.send | بله | یک کلید idempotency، تکرار را به بازپخش تبدیل میکند. |
| emails.cancel، emails.reschedule، broadcasts.cancel، forms.publish، forms.pause، forms.resume، forms.approve_submission، account.accept_invitation، account.decline_invitation | بله | یک تنظیم خالصِ حالتی نامبرده. |
| threads.update، threads.trash، threads.restore | بله | تنظیم برچسب است. دو بار اعمال کردنش همان یک بار اعمال کردن است. |
| threads.snooze, threads.unsnooze | بله | لحظهٔ بیدارباش در بدنه است، نه مشتقشده از زمان رسیدن. |
| labels.update، webhooks.update، settings.update، roles.update، members.update، domains.update، contacts.update، audiences.update، keys.update، emails.update، forms.update، branding.update، chats.rename، threads.update_note، domains.update_address، domains.update_address_forward، 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 | بله | اعطا یک upsert است، و ترتیب بهطور کامل بیان میشود. |
| templates.publish, imports.start | بله | انتشار سری که از پیش منتشر شده است، یا آغاز ایمپورتی که از پیش آغاز شده است، همان را بدون تغییر برمیگرداند. |
| templates.preview، templates.render، broadcasts.preview، rules.test | بله | رندر میکنند، میشمارند یا ارزیابی میکنند و چیزی نمینویسند. |
| domains.verify, app_host.verify | بله | بررسی تکراری چیزی جز زمان بررسی را تغییر نمیدهد. |
| contacts.save، contacts.set_audiences، contacts.remove_photo، contacts.block، contacts.unblock، contacts.delete_many، keys.revoke، account.remove_photo، branding.remove_image، domains.remove_logo، domains.remove_logo_certificate، domains.remove_address_photo، app_host.delete، files.revoke_link، files.revoke_all_links، subscriptions.move | بله | هرکدام نتیجهٔ نهایی را بیان میکند، پس فراخوانی دوم همان چیزی را به جا میگذارد که اولی به جا گذاشت. |
| audiences.add_contact، audiences.add_contacts، audiences.remove_contacts، audiences.import_contacts، suppressions.add، domains.create_address، senders.research | بله | تکرار، کار فراخوانی اول را انجامشده مییابد و بهجای دو بار انجام دادنش آن را گزارش میکند. |
| contacts.set_photo، imports.upload_chunk، account.set_photo، branding.upload_image، domains.set_logo، domains.set_logo_certificate، domains.set_address_photo | بله | بایتهایی که دوباره فرستاده میشوند جایگزین چیزی میشوند که تلاش اول ذخیره کرده بود. |
| drafts.create، labels.create، webhooks.create، templates.create، rules.create، roles.create، temp_mail.create، files.upload، templates.design، forms.design | خیر | تلاش مجدد دو شیء به جا میگذارد. |
| drafts.update | خیر | بهجای استفادهٔ دوباره از شناسهای که فرستادهاید، شناسه را از نتیجهٔ هر نوشتن بخوانید. |
| drafts.delete، labels.delete، webhooks.delete، templates.delete، rules.delete، roles.delete، members.remove، members.revoke_address، temp_mail.delete، temp_mail.delete_message | خیر | تلاش مجدد پس از گم شدن یک پاسخ، برای کاری که موفق شده است شکست گزارش میکند. |
| webhooks.rotate_secret | خیر | چرخش دوم، کلید مخفیای را که تلاش اول برگردانده بود باطل میکند. |
| webhooks.test | خیر | یک تحویل ساختگی دوم میفرستاد. |
| webhooks.replay_delivery | خیر | رویداد را بار دوم به گیرندهٔ شما میفرستاد. |
| emails.translate | خیر | فراخوانی مدل خرج میکند، پس تلاش مجدد پس از درخواستی بیپاسخ، همان پاسخ را دو بار میخرد. |
| emails.compose، emails.rewrite، emails.suggest_subject | خیر | هر تلاش یک کنش هوش مصنوعی دیگر مصرف میکند و با پاسخی متفاوت برمیگردد. |
| هر فراخوانی دیگر | خیر | یک بار فرستاده میشود، و شکست گزارش میشود نه تکرار. |
forms.update حتی با expectedUpdatedAt هم دوباره تلاش میشود، پس تلاش دوباره پس از یک پاسخ گمشده ممکن است با 409 version_conflict برگردد، چون تلاش نخست انجام شده بود. پیش از تلاش دوباره، فرم را بخوانید.
client.raw.request یک GET را دوباره تلاش میکند و هر چیز دیگری را یک بار میفرستد، مگر اینکه repeatable=True بدهید.
بکآف
- محدود به
max_retriesروی کلاینت، که پیشفرضش دو تلاش اضافی است. - تنها پس از یک شکست شبکه یا یکی از
408،500،502،503یا504. یک429فقط وقتی دوباره تلاش میشود کهRetry-Afterداشته باشد، و این API چنین چیزی نمیفرستد، پس محدودیت نرخ بیدرنگ raise میشود. هر status دیگری فوراً raise میشود. - نمایی از نیم ثانیه تا هشت ثانیه، با jitter، تا یک ناوگان هنگام بازیابی دوباره همزمان نشود.
- با
Retry-Afterدر هر دو شکلش تنظیم میشود، delay-seconds و HTTP-date. وقتی سرور مدت انتظاری را نام ببرد، کلاینت دقیقاً همانقدر صبر میکند بهجای عقبنشینی نمایی. - سروری که بیش از یک دقیقه بخواهد، چنین تفسیر میشود که به کلاینت میگوید بایست، نه اینکه بخواب؛ پس خطا با
retry_after_secondsروی آن بالا میرود. زودتر از آنچه خواسته بازگشتن، احترام گذاشتن به آن نیست. timeoutهر تلاش را محدود میکند، پس فراخوانیای که هر دو تلاش دوبارهاش را به کار ببرد ممکن است به اندازهٔ سه تایماوت بهعلاوهٔ انتظارهای میان آنها طول بکشد.- لغو یک فراخوانی
AsyncOpenEmailهرگز دوباره تلاش نمیشود. لغو بیدرنگ منتشر میشود، چه از درخواست چه از انتظار پیش از تلاش بعدی.