پرش به مستندات
PHP

تلاش مجدد و idempotency

چه چیزی دوباره تلاش می‌شود، چه چیزی عمداً نه، و چرا یک ارسالِ دوباره‌تلاش‌شده نمی‌تواند تکراری شود.

ارسال‌ها

کلاینت به هر ارسال (emails->send، emails->sendBatch، templates->send و broadcasts->send) یک Idempotency-Key می‌چسباند که به‌ازای هر فراخوانی یک بار به شکل oe- و یک UUID تصادفی تولید می‌شود و همان فراخوانی در تلاش‌های دوباره‌اش از آن استفاده می‌کند. API پیش از آنکه چیزی را روانه کند آن کلید را ثبت می‌کند، پس یک تلاش دوباره همان پیام اصلی را بازپخش می‌کند نه اینکه پیام دومی بفرستد، در حالی که دو فراخوانی عمدی send همچنان دو بار می‌فرستند. این‌ها دو نیت متفاوت‌اند و متفاوت می‌مانند.

با دادن idempotencyKey: خودتان، این تضمین را در میان فرایندها گسترش دهید، تا کاری که از کار افتاده و دوباره اجرا شده است ارسال‌هایش را بازپخش کند نه اینکه تکرارشان کند. بازپخش با replayed برابر true و پیام ذخیره‌شده در وضعیت کنونی‌اش پاسخ می‌دهد.

idempotency.php
$invoiceId = 'inv_2026_09_4192'; $sent = $client->emails->send([    'from' => '[email protected]',    'to' => '[email protected]',    'subject' => 'Your September invoice',    'text' => 'Invoice attached.',], idempotencyKey: 'invoice:' . $invoiceId); echo $sent['id'], ' ', ($sent['replayed'] ?? false) ? 'replayed' : 'sent', PHP_EOL;

آن را از همان چیزی مشتق کنید که ارسال را لازم کرده است. هرگز از ساعت. استفادهٔ دوباره از یک کلید با بدنه‌ای متفاوت با یک 422 idempotency_key_reuse رد می‌شود، نه اینکه بی‌صدا بازپخش شود. کلید 1 تا 255 نویسه از حروف، ارقام، _، .، : یا - است، و هر چیز دیگری یک 400 invalid_idempotency_key است.

باقی موارد

هر GET دوباره تلاش می‌شود. یک نوشتن تنها جایی دوباره تلاش می‌شود که درخواست دومِ همسان نتواند معنایی متفاوت از اولی داشته باشد، و ارسال واجد شرایط است چون کلید idempotency آن یک تکرار را به بازپخش تبدیل می‌کند.

فراخوانیتلاش مجددچرا
هر GETبلهچیزی تغییر نمی‌کند.
emails->send, emails->sendBatch, templates->send, broadcasts->sendبلهیک کلید idempotency، تکرار را به بازپخش تبدیل می‌کند.
emails->cancel, emails->reschedule, broadcasts->cancel, forms->pause, forms->resume, threads->restoreبلهیک تنظیم خالصِ حالتی نام‌برده.
threads->update, threads->trashبلهتنظیم برچسب است. دو بار اعمال کردنش همان یک بار اعمال کردن است.
threads->snooze, threads->unsnoozeبلهلحظهٔ بیدارباش در بدنه است، نه مشتق‌شده از زمان رسیدن.
emails->update, labels->update, webhooks->update, settings->update, roles->update, members->update, domains->update, domains->updateAddress, domains->updateAddressForward, contacts->update, audiences->update, keys->update, forms->update, branding->update, threads->updateNote, chats->rename, account->setEmailNotification, account->setPushMuted, appHost->set, workspaces->setActiveبلهیک تنظیم خالصِ فیلدهای نام‌برده.
members->grantAddress, members->grantDomain, rules->reorder, threads->reorderNotesبلهاعطا یک upsert است، و ترتیب به‌طور کامل بیان می‌شود.
templates->publish, forms->publish, imports->startبلهانتشار چیزی که از پیش منتشر شده است، یا آغاز ایمپورتی که از پیش آغاز شده است، همان را بدون تغییر برمی‌گرداند.
templates->preview, templates->render, broadcasts->preview, rules->testبلهرندر می‌کنند، می‌شمارند یا ارزیابی می‌کنند و چیزی نمی‌نویسند.
domains->verify, appHost->verify, senders->researchبلهبررسی تکراری چیزی جز زمان انجامش را تغییر نمی‌دهد.
contacts->save, contacts->setAudiences, contacts->removePhoto, contacts->block, contacts->unblock, contacts->deleteMany, keys->revoke, files->revokeLink, files->revokeAllLinks, appHost->delete, account->removePhoto, branding->removeImage, domains->removeLogo, domains->removeLogoCertificate, domains->removeAddressPhoto, account->acceptInvitation, account->declineInvitation, forms->approveSubmission, subscriptions->moveبلههرکدام نتیجهٔ نهایی را بیان می‌کند، پس فراخوانی دوم همان چیزی را به جا می‌گذارد که اولی به جا گذاشت.
audiences->addContact, audiences->addContacts, audiences->removeContacts, audiences->importContacts, suppressions->add, domains->createAddressبلهتکرار، کار فراخوانی اول را انجام‌شده می‌یابد و به‌جای دو بار انجام دادنش آن را گزارش می‌کند.
contacts->setPhoto, account->setPhoto, branding->uploadImage, domains->setLogo, domains->setLogoCertificate, domains->setAddressPhoto, imports->uploadChunkبلهبایت‌هایی که دوباره فرستاده می‌شوند جایگزین چیزی می‌شوند که تلاش اول ذخیره کرده بود.
drafts->create, labels->create, webhooks->create, templates->create, rules->create, roles->create, tempMail->create, files->uploadخیرتلاش مجدد دو شیء به جا می‌گذارد.
drafts->updateخیربه‌جای استفادهٔ دوباره از شناسه‌ای که فرستاده‌اید، شناسه را از نتیجهٔ هر نوشتن بخوانید.
drafts->delete, labels->delete, webhooks->delete, templates->delete, rules->delete, roles->delete, members->remove, members->revokeAddress, tempMail->delete, tempMail->deleteMessageخیرتلاش مجدد پس از گم شدن یک پاسخ، برای کاری که موفق شده است شکست گزارش می‌کند.
webhooks->rotateSecretخیرچرخش دوم، کلید مخفی‌ای را که تلاش اول برگردانده بود باطل می‌کند.
webhooks->testخیریک تحویل ساختگی دوم می‌فرستاد.
webhooks->replayDeliveryخیررویداد را بار دوم به گیرندهٔ شما می‌فرستاد.
emails->translate, emails->compose, emails->rewrite, emails->suggestSubjectخیرهرکدام فراخوانی مدل خرج می‌کند، پس تلاش دوباره پس از درخواستی بی‌پاسخ، همان پاسخ را دو بار می‌خرد.
security->beginStepUp, security->verifyStepUpخیرتلاش دوباره ممکن است ایمیل دومی بفرستد یا تلاش دومی را روی کد مصرف کند.
هر فراخوانی دیگری که GET نیستخیریک بار فرستاده می‌شود، و شکست گزارش می‌شود نه تکرار.

بک‌آف

  • محدود به maxRetries: روی کلاینت، که پیش‌فرضش دو تلاش اضافی است. maxRetries: 0 تلاش‌های دوباره را خاموش می‌کند.
  • تنها پس از یک شکست شبکه یا یکی از 408، 500، 502، 503 یا 504. یک 429 فقط وقتی دوباره تلاش می‌شود که Retry-After داشته باشد، و این API چنین چیزی نمی‌فرستد، پس محدودیت نرخ بی‌درنگ throw می‌شود. هر status دیگری فوراً throw می‌شود.
  • نمایی از نیم ثانیه تا هشت ثانیه، با jitter: هر انتظار نقطه‌ای تصادفی میان نیمی از آن سقف و کل آن است، تا یک ناوگان هنگام بازیابی دوباره هم‌زمان نشود.
  • با Retry-After در هر دو شکلش تنظیم می‌شود، delay-seconds و HTTP-date. وقتی سرور مدت انتظاری را نام ببرد، کلاینت دقیقاً همان‌قدر صبر می‌کند به‌جای عقب‌نشینی نمایی.
  • سروری که بیش از یک دقیقه بخواهد، چنین تفسیر می‌شود که به کلاینت می‌گوید بایست، نه اینکه بخواب، پس استثنا با retryAfterSeconds روی آن پرتاب می‌شود. زودتر از آنچه خواسته بازگشتن، احترام گذاشتن به آن نیست.
  • پایان مهلت هم یک شکست شبکه است مانند هر شکست دیگر، پس فراخوانی‌ای که تکرارش بی‌خطر است پس از آن دوباره امتحان می‌شود، و timeout: برای هر تلاش از نو اعمال می‌شود.
  • انتظارها فراخوانی‌های sleep و usleep درون همان فراخوانی هستند، پس اسکریپت هم منتظر می‌ماند، و فراخوانی تنها وقتی آخرین تلاشش تمام شد برمی‌گردد یا استثنا پرتاب می‌کند. در یک درخواست وب که شخصی منتظرش است، timeout: و maxRetries: را پایین نگه دارید.