منطق إعادة المحاولة
فهم كيفية إعادة Mail.Land لمحاولة تسليم webhook الفاشلة
عندما تفشل عملية تسليم webhook، تُعيد MailLand المحاولة تلقائياً مع تأخيرات متزايدة. تغطي هذه الصفحة جدول إعادة المحاولة، وحالات التسليم، ومعالجة الأخطاء، وكيفية مراقبة عمليات التسليم وإعادة محاولتها يدوياً.
جدول إعادة المحاولة
يغطي هذا القسم كل حدث يسلّمه durable dispatcher: message.* وsuppression.* وaccount.*
وinbound.received. ما يخص أحداث البريد الوارد موجود في تسليمات البريد الوارد
أدناه.
تُعيد MailLand محاولة التسليم الفاشل حتى 6 مرات إجمالاً، مع تأخير متزايد قبل كل محاولة إعادة:
| المحاولة | التأخير قبل هذه المحاولة | إجمالي الوقت المنقضي |
|---|---|---|
| 1 | : (المحاولة الأولى) | 0 |
| 2 | فوري | ~0 |
| 3 | دقيقة واحدة | ~دقيقة واحدة |
| 4 | 5 دقائق | ~6 دقائق |
| 5 | 15 دقيقة | ~21 دقيقة |
| 6 | ساعة واحدة | ~ساعة و21 دقيقة |
بعد فشل المحاولة السادسة، يُصنَّف التسليم على أنه فاشل نهائياً: لا يوجد انتظار إضافي ولا محاولة سابعة.
قابل للإعادة مقابل غير قابل للإعادة
الردود القابلة لإعادة المحاولة
تؤدي رموز الحالة هذه إلى إعادة المحاولة تلقائياً:
408Request Timeout429Too Many Requests500Internal Server Error502Bad Gateway503Service Unavailable504Gateway Timeout- أخطاء الشبكة (انتهاء المهلة، أخطاء المقبس، إخفاقات DNS)
الردود غير القابلة لإعادة المحاولة
تُعامَل رموز الحالة هذه كإخفاقات دائمة، لا تتم إعادة المحاولة:
400Bad Request401Unauthorized403Forbidden404Not Found- جميع أخطاء
4xxالأخرى (باستثناء 408 و429) - استجابة إعادة توجيه فشلت في التحقق (راجع عمليات إعادة التوجيه) أو تجاوزت حد عدد القفزات
إذا أعادت نقطة النهاية لديك رأس Retry-After على استجابة قابلة لإعادة المحاولة، تستخدم MailLand
تلك القيمة كتأخير قبل المحاولة التالية بدلاً من الجدول أعلاه: لأي حالة قابلة لإعادة المحاولة، وليس
فقط 429. لا يوجد حد أقصى ولا تذبذب عشوائي (jitter) يُطبَّق عليها: احترم هذا في جانبك أيضاً إذا
أرسلته، لأن قيمة كبيرة جداً تُحترم كما هي تماماً.
عمليات إعادة التوجيه
لا تتعامل MailLand مع نقطة النهاية لديك كما يفعل المتصفح. تُتَّبع عمليات إعادة التوجيه يدوياً، بحد أقصى 3 قفزات، ويُعاد التحقق من كل قفزة قبل إرسال أي شيء إليها:
- يجب أن يكون الهدف
https://: إعادة التوجيه إلىhttp://تُرفض ولا تُخفَّض؛ - يجب أن يُحلَّل الهدف إلى عنوان عام: إعادة التوجيه إلى عنوان خاص أو loopback أو link-local تُرفض، ولا يُرسَل الطلب أبداً؛
- تجاوز 3 قفزات يفشل التسليم.
يُبلَّغ عن إعادة التوجيه المرفوضة كفشل تسليم بدون رمز حالة. إذا انتقلت نقطة النهاية لديك، وجّه webhook إلى العنوان الجديد بدلاً من الاعتماد على إعادة توجيه.
إعداد التسليم
| الإعداد | الافتراضي | الوصف |
|---|---|---|
| مهلة HTTP | 15 ثانية | الحد الأقصى لوقت الانتظار لكل محاولة تسليم |
| الحد الأقصى لإعادة المحاولة | 6 محاولات | إجمالي محاولات التسليم بما في ذلك الأولى |
| عتبة الإيقاف التلقائي | 10 إخفاقات متتالية | يُوقف webhook بعد هذا العدد من الإخفاقات المتتالية: يُستخدم pauseThreshold الخاص بالـwebhook عند ضبطه على قيمة أكبر من 0، وإلا فهذه القيمة الافتراضية |
| إلغاء التكرار | طالما بقي سجل التسليم موجوداً | تُستبعد تكرارات الحدث نفسه بقيد (WebhookId, EventId) طالما بقي السطر موجوداً: 30 يوماً على الأقل للتسليمات الناجحة |
تسليمات البريد الوارد
يُسلَّم inbound.received عبر durable dispatcher نفسه مثل كل حدث آخر، بجدول إعادة المحاولة نفسه ومعالجة
Retry-After نفسها وسجل التسليم نفسه والإيقاف المؤقت التلقائي نفسه الموصوفة أعلاه.
- ألغِ التكرار على
event_id(يساويX-MLND-Event-Id) كما في أي حدث آخر. وهو ثابت لكل رسالة واردة ولكل ويب هوك، لذا تحمل كل محاولة للبريد نفسه المعرّف نفسه. - إعادة التشغيل اليدوية حدث جديد:
event_idجديد، والمعرّف الأصلي فيdata.replay_of. ويبقىdata.idempotency_keyكما هو. - يُوقَّع
download_urlلكل مرفق في كل محاولة ويبقى صالحًا 15 دقيقة من حينها؛ وidالمرفق هو نفسه في كل محاولة. راجع ويب هوك البريد الوارد.
عرض سجل التسليم
اطّلع على عمليات التسليم السابقة لـ webhook:
GET https://api.mail.land/v1/webhooks/{id}/deliveriescurl -X GET "https://api.mail.land/v1/webhooks/wh_abc123/deliveries?limit=20" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."معاملات الاستعلام
| المعامل | النوع | الافتراضي | الوصف |
|---|---|---|---|
cursor | string | - | مؤشر معتم من nextCursor للصفحة السابقة. احذفه للصفحة الأولى. |
limit | int | 20 | العناصر لكل صفحة |
status | string | - | تصفية: success أو failed |
eventType | string | - | التصفية حسب نوع الحدث (مثلاً message.delivered) |
from | datetime | - | تاريخ البداية |
to | datetime | - | تاريخ النهاية |
{
"items": [
{
"publicId": "p8r2kx7m9wq4rtz",
"eventType": "message.delivered",
"messageId": "t_a1b2c3d4e5f6",
"statusCode": 200,
"responseTimeMs": 145,
"success": true,
"errorMessage": null,
"createdAt": "2026-02-17T12:34:58.000Z",
"attemptNumber": 1
},
{
"publicId": "p8r2kx7m3nq1abc",
"eventType": "message.bounced",
"messageId": "t_d4e5f6a1b2c3",
"statusCode": 503,
"responseTimeMs": 15000,
"success": false,
"errorMessage": "Service Unavailable",
"createdAt": "2026-02-17T12:30:00.000Z",
"attemptNumber": 3
}
],
"nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
"hasMore": true
}إعادة محاولة تسليم فاشل
أعِد محاولة تسليم فاشل محدد يدوياً:
POST https://api.mail.land/v1/webhooks/{id}/deliveries/{publicId}/retrycurl -X POST https://api.mail.land/v1/webhooks/wh_abc123/deliveries/p8r2kx7m3nq1abc/retry \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."يُعيد 202 Accepted عند النجاح. تُضاف إعادة المحاولة إلى قائمة الانتظار وتستخدم بيانات الحدث الأصلية.
| الحالة | الرمز | الوصف |
|---|---|---|
202 | - | أُضيفت إعادة المحاولة إلى قائمة الانتظار بنجاح |
202 | - | التسليم موجود بالفعل في قائمة الانتظار لإعادة المحاولة، لا شيء يحدث، وليس خطأ |
400 | ALREADY_SUCCEEDED | لا يمكن إعادة محاولة تسليم نجح بالفعل |
400 | INVALID_REQUEST | التسليم أقدم من تتبّع إعادة المحاولة الدائم، أو قيد التنفيذ حالياً |
404 | WEBHOOK_NOT_FOUND | webhook غير موجود |
404 | DELIVERY_NOT_FOUND | معرّف التسليم غير موجود |
الإيقاف التلقائي عند الإخفاقات
عندما يجمع webhook عددًا كافيًا من الإخفاقات المتتالية، تُوقفه MailLand تلقائياً. العتبة هي pauseThreshold الخاص بالـwebhook عند ضبطه على قيمة أكبر من 0، وإلا فهي القيمة الافتراضية وهي 10 إخفاقات متتالية:
- يُضبط
isActiveالخاص بـ webhook علىfalse، ويُعبَّآنpausedAtوpausedReason: يخبركpausedReasonبعدد الإخفاقات وماهية آخر إخفاق - يُنشأ إشعار داخل التطبيق
- لا تُسلَّم المزيد من الأحداث حتى يُستأنف webhook
العداد هو عداد محاولات، وليس أحداثاً: حدث واحد يستنفد سلّم إعادة المحاولة بأكمله يساهم بعدة إخفاقات.
لا يوجد إشعار تحذيري مبكر قبل بلوغ العتبة: تحقق من consecutiveFailures بشكل استباقي (راجع أفضل
الممارسات أدناه) بدلاً من انتظار إخطارك.
استئناف webhook موقوف
POST https://api.mail.land/v1/webhooks/{id}/resumecurl -X POST https://api.mail.land/v1/webhooks/wh_abc123/resume \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."يعيد هذا تفعيل webhook: يمسح حالة الإيقاف، ويعيد تعيين عداد الإخفاقات المتتالية إلى الصفر، ويضبطه نشطاً مجدداً. ستُحاول عملية التسليم التالية بشكل طبيعي.
أي تسليم ناجح يُعيد تعيين عداد الإخفاقات المتتالية إلى الصفر تلقائياً. نجاح واحد بعد 9 إخفاقات يمنع إيقاف webhook.
أفضل الممارسات
- أعِد 200 بسرعة: عالج حمولات webhook بشكل غير متزامن. ضَع الحدث في قائمة الانتظار وأعِد
200فوراً. المعالجات طويلة المدى تخاطر بانتهاء المهلة. - استخدم معرّف الحدث للمعالجة المتكرِّرة الآمنة (idempotent): رأس
X-MLND-Event-Id(والحقل المطابقevent_idفي الحمولة) ثابت عبر إعادة المحاولات وإعادة الإرسال: يصل نفس الحدث الأصلي دائماً بنفس المعرّف، بغض النظر عن عدد مرات إعادة تسليمه. خزّن المعرّفات المعالَجة وتجاوز ما عالجته من قبل، بحيث يكون التسليم المكرر بلا أثر إضافي في جانبك. - راقب الإخفاقات المتتالية: تحقق من حقل
consecutiveFailuresعند إدراج webhooks. حقق الأمر قبل الوصول إلى عتبة الإيقاف التلقائي. - تعامل مع 429 بشكل صحيح: إذا كانت نقطة النهاية مثقلة، أعِد
429مع رأسRetry-After. ستحترم MailLand ذلك.
الخطوات التالية
- التحقق من التوقيع: التحقق من صحة webhook
- الأحداث: مرجع شامل لأنواع الأحداث
- نظرة عامة على Webhooks: إنشاء وإدارة webhooks