Resilience לשירותים חיצוניים

למה שכבה מרוכזת?

המעבר למודול resilience.py יוצר אחידות: כל קריאה החוצה עוברת דרך אותה מדיניות Retry + Circuit Breaker. התוצאה: פחות רעשים זמניים, ניטור ברור יותר, ויכולת להבין בזמן אמת מתי שירות חוץ ”שורף“ אותנו.

איך זה עובד?

  • RetryPolicy: כמה ניסיונות חוזרים, ו‑Backoff אקספוננציאלי עם jitter למניעת ”עדר“.

  • CircuitBreaker: פתיחה/half-open/סגירה לפי כשלים רצופים וחלונות הצלחה.

  • כל הקביעות נשלטות דרך ENV, ללא שינוי קוד.

דיאגרמת טיפול בשגיאות

התרשים הבא מציג את הזרימה המלאה של טיפול בשגיאות ושחזור:

        graph TD
    E[Error Occurs] --> ET{Error Type}

    ET -->|Database| DBE[DB Error Handler]
    ET -->|API| APE[API Error Handler]
    ET -->|Timeout| TE[Timeout Handler]
    ET -->|Unknown| UE[Generic Handler]

    DBE --> RT1{Retry?}
    RT1 -->|Yes| RTC1[Retry with Backoff]
    RT1 -->|No| FO1[Failover to Cache]

    APE --> RT2{Rate Limited?}
    RT2 -->|Yes| BK[Activate Backoff]
    RT2 -->|No| RTC2[Retry Request]

    TE --> CX[Cancel Operation]
    CX --> NF[Notify User]

    UE --> LOG[Log Error]
    LOG --> ALT[Alert Admin]

    RTC1 --> SR{Success?}
    RTC2 --> SR
    FO1 --> SR
    BK --> SR

    SR -->|Yes| RES[Return Result]
    SR -->|No| ERR[Return Error]
    

סוגי שגיאות והטיפול:

  • Database Errors: ניסיון חוזר עם Backoff, או Failover ל-Cache

  • API Errors: בדיקת Rate Limit, הפעלת Backoff או Retry

  • Timeout Errors: ביטול הפעולה והודעה למשתמש

  • Unknown Errors: לוגים + התראה לאדמין

עקרונות מרכזיים:

  1. זיהוי סוג השגיאה לטיפול מותאם

  2. Retry עם Backoff אקספוננציאלי למניעת עומס

  3. Failover אוטומטי לשירותי גיבוי (Cache)

  4. התראות לאדמין בשגיאות קריטיות

קונפיגורציה חשובה (ENV)

ENV

משתנה

ברירת מחדל

מה הוא עושה

HTTP_RESILIENCE_MAX_ATTEMPTS

3

ניסיונות חזרה לפני שמפסיקים

HTTP_RESILIENCE_BACKOFF_BASE

0.25

זמן ההמתנה הראשון (שניות) לפני כניסה לאקספוננט

HTTP_RESILIENCE_BACKOFF_MAX

8.0

תקרת ההמתנה בין ניסיונות

HTTP_RESILIENCE_JITTER

0.5

רעש אקראי (שניות) לכל המתנה

CIRCUIT_BREAKER_FAILURE_THRESHOLD

5

כמה כשלונות לפני פתיחת Circuit

CIRCUIT_BREAKER_RECOVERY_SECONDS

30

כמה זמן ממתינים עד ניסיון half-open

CIRCUIT_BREAKER_HALF_OPEN_SUCCESS

1

כמה הצלחות רצופות נדרשות כדי לסגור Circuit

CIRCUIT_BREAKER_SUCCESS_WINDOW

20

חלון לחישוב אחוזי הצלחה

טיפ

אם שירות חוץ מתחיל להחזיר 429, ניתן זמנית להגדיל CIRCUIT_BREAKER_RECOVERY_SECONDS כדי למנוע עומס חוזר.

שימוש בקוד

כברירת מחדל, כל הקריאות דרך http_sync.request ו‑http_async.request עובדות עם המדיניות הזו. ניתן להעביר שמות שירות/נתיב לקבלת מטריקות נקיות.

from http_sync import request

resp = request(
    "GET",
    "https://status.github.com/api",
    service="github",
    endpoint="status_api",
)

ראו גם