تخطَّ إلى المستندات
SDK

إعادة المحاولة واللاتكرارية

ما يُعاد، وما لا يُعاد عن قصد، ولماذا لا يمكن لإرسال مُعاد أن يتضاعف.

الإرسالات

يرفق العميل ترويسة Idempotency-Key بكل إرسال (emails.send وemails.sendBatch وtemplates.send)، تُولَّد مرة واحدة لكل **نداء** وتعيد محاولات ذلك النداء استخدامها. ويحجز API ذلك المفتاح قبل أن يرسل أي شيء، فتعيد المحاولة تشغيل الرسالة الأصلية بدل إرسال ثانية، بينما يظل نداءا send() المتعمّدان يرسلان مرتين. فهاتان نيتان مختلفتان وتبقيان مختلفتين.

مرّر idempotencyKey الخاص بك لمدّ ذلك الضمان عبر العمليات، فتُعيد مهمة انهارت ثم عملت من جديد تشغيل إرسالاتها بدل تكرارها.

idempotency.ts
await openemail.emails.send(message, { idempotencyKey: `invoice:${invoice.id}` })

اشتقّه مما جعل الإرسال ضروريًا. ولا تشتقّه من ساعة أبدًا. وإعادة استخدام مفتاح بمتن مختلف تُرفض بـidempotency_key_reuse بدل أن تُعاد صامتةً.

كل ما عدا ذلك

تُعاد كل قراءة. أما الكتابة فلا تُعاد إلا حيث لا يمكن لطلب ثانٍ مطابق أن يعني شيئًا مختلفًا عن الأول، والإرسال مؤهل لذلك لأن مفتاح اللاتكرارية لديه يحوّل التكرار إلى إعادة تشغيل.

النداءيُعادلماذا
كل قراءةنعملا شيء يتغير.
`emails.send`، `emails.sendBatch`، `templates.send`نعممفتاح اللاتكرارية يجعل التكرار إعادة تشغيل.
`emails.cancel`، `emails.reschedule`نعمضبط خالص لحالة مسمّاة.
`threads.update`، `threads.trash`نعمضبط تسميات. وتطبيقه مرتين هو تطبيقه مرة واحدة.
`threads.snooze`، `threads.unsnooze`نعملحظة الاستيقاظ موجودة في المتن، وليست مشتقة من وقت الوصول.
`labels.update`، `webhooks.update`، `settings.update`، `roles.update`، `members.update`نعمضبط خالص لحقول مسمّاة.
`members.grantAddress`، `rules.reorder`نعمالمنحة إدراج أو تحديث، والترتيب مذكور بالكامل.
`templates.publish`نعمنشر رأس منشور أصلًا يعيده دون تغيير.
`templates.preview`، `rules.test`نعميعرضان أو يقيّمان، ولا يكتبان شيئًا.
`drafts.create`، `labels.create`، `webhooks.create`، `templates.create`، `rules.create`، `roles.create`، `tempMail.create`لاإعادة المحاولة تترك كائنين.
`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`لاسيرسل تسليمًا اصطناعيًا ثانيًا.
`emails.translate`لاينفق نداءات نموذج، فإعادة المحاولة بعد طلب بلا جواب تشتري الجواب نفسه مرتين.
كل كتابة أخرىلاتُرسل مرة واحدة، ويُبلَّغ عن الإخفاق بدل تكراره.

التراجع التدريجي

  • محدودة بـmaxRetries على العميل، وافتراضها محاولتان إضافيتان.
  • لا تحدث إلا بعد إخفاق في الشبكة أو 408 أو 500 أو 502 أو 503 أو 504. ولا يُعاد 429 إلا حين يحمل ترويسة Retry-After، وهذا API لا يرسلها، فيرمي حدّ المعدل استثناءً فورًا. وأي رمز حالة آخر يرمي في الحال.
  • أسّية من نصف ثانية حتى ثماني ثوانٍ، مع تشويش زمني، كي لا يعيد أسطول من العملاء مزامنة نفسه عند التعافي.
  • تُضبط وتيرتها بـRetry-After بأي من صيغتيها، delay-seconds وHTTP-date. وحين يحدّد الخادم مدة انتظار، ينتظر العميل تلك المدة بالضبط بدل التراجع التدريجي.
  • الخادم الذي يطلب أكثر من دقيقة يُعامَل كمن يقول للعميل توقّف لا نَمْ، فيُرفع الخطأ ومعه retryAfterSeconds. فالعودة قبل ما طلب ليست احترامًا لطلبه.
  • لا يُعاد أبدًا طلب أُجهض بـAbortSignal من المنادي. فالإجهاض يرمي OpenEmailNetworkError في الحال، من الطلب أو من الانتظار السابق للمحاولة التالية.