AzLearn

بناء مُزخرف retry

Build a Retry Decorator

تطبيق ~25 دقيقة

بناء مُزخرف retry — Build a Retry Decorator

في التطوير الحقيقي، العمليات تفشل: طلبات الشبكة تنتهي مهلتها، قواعد البيانات تكون مشغولة، الخدمات الخارجية تتعطل. الحل الاحترافي هو الإعادة التلقائية عند الفشل (Retry) — وأفضل مكان لهذا المنطق هو مُزخرف قابل للإعادة الاستخدام.

ستبني هذا المُزخرف خطوة بخطوة، بدءاً من النسخة الأبسط ووصولاً لنسخة إنتاجية متكاملة. كل خطوة تبني على السابقة.

الخطوة 1 — مُزخرف بسيط (بدون إعداد)

أولاً، نبني مُزخرفاً يُعيد المحاولة مرتين إضافيتين عند أي فشل — من غير معاملات (لا factory بعد).

main.go

المُزخرف يلتقط Exception، يطبع رسالة، ويُعيد المحاولة. إذا استنفد كل المحاولات يُعيد إطلاق آخر خطأ لكي يُعالجه المستدعي.

الخطوة 2 — decorator factory مع times

المُزخرف الثابت غير مرن. نريد @retry(times=5). هذا يتطلب decorator factory — دالة تُنتج مُزخرفاً.

تحدي — Challenge

الخطوة 3 — الإمساك بالاستثناء والإعادة الصحيحة

بنينا الهيكل. الآن نتأكد أن المُزخرف يُعيد رمي الاستثناء إذا استنفدت كل المحاولات، ولا يبتلع الخطأ صامتاً.

main.go

الخطوة 4 — إضافة Backoff أسّي

إعادة المحاولة فوراً قد تُرهق الخادم. في الإنتاج نضيف تأخير يتضاعف بعد كل فشل: 1s، 2s، 4s…

تحدي — Challenge

الخطوة 5 — تصفية الاستثناءات

أحياناً تريد الإعادة فقط عند استثناءات معينة. خطأ ValueError (بيانات خاطئة) لا يستحق إعادة — أما ConnectionError فيستحق.

تحدي — Challenge

النسخة الكاملة — Full Production Version

الآن نجمع كل الخطوات في مُزخرف واحد إنتاجي:

main.go

الخلاصة — Summary

المُزخرف retry الذي بنيته يجسّد كل ما تعلمته في هذا الفصل:

  • الدوال كقيمdecorator تأخذ fn وتُرجع wrapper
  • decorator factoryretry(times, delay, ...) تُنتج مُزخرفاً قابلاً للإعداد
  • functools.wraps — يحفظ اسم ووثائق الدالة الأصلية
  • *args, **kwargs — يجعل wrapper مرناً مع أي توقيع
  • Type hints — توثيق واضح لكل معامل ونوعه
  • معالجة الاستثناءات — التمييز بين ما يستحق الإعادة وما لا يستحق

هذا النمط موجود في مكتبات Python الشهيرة: tenacity، backoff، retry، وurllib3. الآن تفهم كيف تبنيه من الصفر — وهذا أهم من حفظ API مكتبة.