الـ At-Least-Once Delivery في الـ Outbox Pattern وكيفية التعامل معاه

ليه الـ Outbox Pattern ممكن يبعت الرسالة مرتين؟

بالبلدي كده: ليه الـ Outbox Pattern ممكن يبعت الرسالة مرتين؟ 🚚📬

تخيل إنك صاحب محل، وعندك كشكول وتسجل فيه الأوردرات (ده الـ Outbox Table)، وعندك دليفري مهمته ياخد الأوردر من الكشكول ويروح يسلمه للزبون (ده الـ Message Relay / Background Worker).

لما حد بيطلب أوردر، أنت بتكتب الأوردر في الكشكول وفي نفس اللحظة بتخصم البضاعة من المخزن في Database Transaction واحدة. ✍️✨ الأوردر كده اتسجل صح ومش هيضيع إطلاقاً.


⚠️ إيه بقى سيناريو المشكلة اللي بيخليها At-Least-Once؟

الدليفري بيمشي بالخطوات دي بالضبط:

  1. يشوف الكشكول: يلاقي أوردر مكتوب عليه Pending أو "جديد". 📖
  2. يروح يوصل الأوردر: للزبون (يبعت الرسالة للـ Broker زي RabbitMQ أو Kafka). الزبون استلم الأوردر خلاص! 📦💨
  3. يرجع للمحل يشيّر على الكشكول: إنه تم التوصيل (Mark as Processed / Published). 📝✅

السؤال بقى: إيه اللي يحصل لو الدليفري اتعطل بين خطوة 2 وخطوة 3؟ 💥

تخيل الدليفري وصل الأوردر للزبون خلاص (خطوة 2 تمت)، وهو راجع في السكة للمحل عشان يعلم في الكشكول إن الأوردر وصل... الموتوسيكل بتاعه عطل أو السيرفر وقع! 🛵💥

  • الدليفري الجديد (لما السيستم يقوم تاني): هيفتح الكشكول عشان يشوف الأوردرات المعلقة. 🔄
  • هيلاقي إيه؟ هيلاقي إن الأوردر لسه مكتوب عليه Pending لأن الدليفري الأولاني ملحقش يعلم عليه "تم التوصيل"! 🔍
  • هيعمل إيه؟ بياخد نفس الأوردر ويروح يوصله للزبون تاني! 🚚💨

💡 النتيجة إيه؟

الزبون (اللي هو الـ Consumer أو السيرفس التانية) استلم نفس الرسالة مرتين! 📩📩

عشان كده بنقول إن النمط ده بيكفل At-Least-Once Delivery (يعني الرسالة هتوصل على الأقل مرة واحدة، وأكيد مش هتضيع)، بس مش بيضمن Exactly-Once (يعني ممكن في حالات العطل تتبعت مرتين أو أكثر).


🛠️ بنحلها إزاي في شغلنا؟

عشان نضمن إن السيستم ميتلخبطش لما يجيله أوردر مكرر، لازم الـ Consumer اللي بيستقبل الرسالة يكون Idempotent. 🛡️

يعني بالبلدي: الزبون لو استلم نفس الأوردر مرتين، يبص على رقم الأوردر الفريد (Message ID):

  • 🆕 لو أوردر جديد: ينفذه ويتعامل معاه طبيعي.
  • 🗑️ لو أوردر استلمه قبل كده: يرميه وما يكررش العملية (مثلاً ما يخصمش من الفيزا مرتين أو يبعت إيميل تأكيد مكرر).

Comments

Popular posts from this blog

Best Practices for Storing and Loading JSON Objects from a Large SQL Server Table Using .NET Core

Maxpooling vs minpooling vs average pooling

Polling vs. SignalR: A Detailed Comparison