HookGet English להתחיל בחינם

ניסיונות חוזרים ומניעת כפילויות

מה נשמר בניסיון חוזר, ואיך צרכן נמנע מלטפל באותו אירוע פעמיים.

בקצרה

  • לוח ברירת המחדל הוא שמונה ניסיונות לאורך כ-21 שעות, ואפשר לשנות אותו לכל יעד.
  • ניסיון חוזר שומר על אותו מזהה מסירה, ולכן אפשר לזהות אותו ולהתעלם ממנו בבטחה.
  • למניעת כפילויות יש שני חצאים: המפתח בצד המפרסם, והבדיקה בצד הצרכן.
  • 410 Gone עוצר מיד, כי הצרכן ביטל את ההרשמה. זה לא כשל.
msg_01J8ZQ3F9VBAQ4E1S0TZY6P8YV ⁦order.created⁩ · 2 יחידות
#שעהסטטוס קודזמן תגובהלמה
1 09:41:02 נכשל 503 1,204 ms השירות לא זמין
2 09:41:07 נכשל 503 980 ms ניסיון חוזר אחרי 5 שניות
3 09:41:37 נכשל timeout 15,000 ms ניסיון חוזר אחרי 30 שניות
4 09:46:37 נמסר 200 142 ms ניסיון חוזר אחרי 5 דקות

אותו webhook-id בכל ניסיון, כך שהצרכן יכול לסנן כפילויות.

כל ניסיון מול יעד אחד: מה נשלח, מה חזר, כמה זמן זה לקח וכמה חיכינו לפני הניסיון הבא. זו התשובה לשאלה "שלחתם או לא?" בלי שאילתה למסד הנתונים.

כל מערכת מסירה צריכה להחליט מה עושים כשהיעד לא עונה. מי שמוותר מיד מאבד אירועים בכל פריסה. מי שמנסה שוב מיד ובלי סוף מפגיז יעד שכבר מתקשה. התשובה היא לוח זמנים שמתחיל מהר ומתרחב, ולצדו צרכן שמוכן לקבל את אותו אירוע יותר מפעם אחת.

הלוח

ניסיוןהמתנה לפניו
1אין, מיידי
230 שניות
32 דקות
410 דקות
530 דקות
62 שעות
76 שעות
812 שעות

בסך הכול כ-21 שעות, מספיק כדי לעבור פריסה, חידוש תעודה ורוב התקלות. המרווחים הקצרים בהתחלה תופסים את הכשלים הרגעיים, והארוכים בסוף נותנים לצוות זמן לתקן בלי שהיעד יוצף. יעד שצריך משהו אחר מקבל לוח משלו:

curl -X PATCH https://api.hookget.com/v1/endpoints/ep_… \
  -H "authorization: Bearer $HOOKGET_KEY" \
  -d '{"retry_schedule":[0,10,60,300],"max_attempts":4}'

מניעת כפילויות משני הצדדים

בצד המפרסם. שלחו מפתח ייחודיות (idempotency key) עם הפרסום, ואותו מפתח לעולם לא ייצור אירוע שני, לא משנה כמה פעמים התשתית שלכם עצמה שולחת את הבקשה מחדש. זה חשוב כי גם הקריאה שלכם ל-API יכולה ליפול באמצע, ואז אין לכם דרך לדעת אם האירוע נשמר. עם מפתח, פשוט שולחים שוב.

-d '{"type":"order.created","payload":{…},"idempotency_key":"ord_10241-created"}'

בצד הצרכן. webhook-id נשאר קבוע בכל ניסיון חוזר של אותה מסירה. שמרו אותו והתעלמו מכל מה שכבר טיפלתם בו:

const id = headers['webhook-id'];
if (await seen(id)) return res.status(200).end();   // already handled
await handle(event);
await remember(id);                                  // then remember it
res.status(200).end();

הסדר בקוד הזה מכוון. קודם בודקים אם המזהה כבר הופיע, ואם כן עונים 200 ולא עושים כלום, כי מבחינת השולח המסירה הצליחה. אחר כך מטפלים באירוע, ורק בסוף שומרים את המזהה, כדי שכשל באמצע הטיפול לא יסמן את האירוע כמטופל.

עונים מהר ועובדים אחר כך. צרכן שמעבד שלושים שניות לפני שהוא עונה יקבל ניסיון חוזר בזמן שהוא עדיין עובד, ואז יצטרך להתמודד עם כפילות גם מול העבודה החצי גמורה של עצמו.

מה עוצר את הלוח מוקדם

תשובהמה קורה
2xxנמסר. הניסיון נרשם ומונה הכשלים מתאפס
410 Goneהיעד מושבת מיד, כי הוא הסיר את עצמו
4xx (אחר)ניסיון חוזר: 401 הוא בדרך כלל סוד חתימה שהוחלף, לא סירוב קבוע
5xx, ‏timeout או שגיאת חיבורניסיון חוזר לפי הלוח
הלוח נגמרעובר לתור הכשלים (DLQ) ונשמר

שאלות

כמה פעמים HookGet מנסה שוב מסירה שנכשלה?

בלוח ברירת המחדל יש שמונה ניסיונות, לאורך כ-21 שעות: הראשון מיידי, והמרווחים גדלים מ-30 שניות ועד 12 שעות. אפשר להגדיר לוח אחר לכל יעד, עם מרווחים ומספר ניסיונות משלו.

למה הצרכן שלי קיבל את אותו אירוע פעמיים?

כמעט תמיד בגלל ניסיון חוזר. היעד טיפל באירוע, אבל התשובה לא הגיעה בזמן, או שהחיבור נפל אחרי העיבוד, ומבחינת השולח המסירה נכשלה. זה לא באג שצריך לתקן, אלא בדיוק המנגנון שמונע אובדן אירועים. הפתרון הוא בצד המקבל: לשמור את webhook-id ולדלג על מה שכבר טופל.

מה ההבדל בין מפתח ייחודיות בפרסום לבין webhook-id?

מפתח הייחודיות (idempotency key) שומר על הצד שלכם: אותו מפתח בפרסום לעולם לא יוצר אירוע שני. webhook-id שומר על הצרכן: הוא קבוע בכל ניסיון חוזר של מסירה, ולכן הצרכן יכול לזהות כפילות. צריך את שניהם, כי כל אחד סוגר פער אחר.

למה 401 מקבל ניסיון חוזר ולא עוצר את הלוח?

כי 401 הוא בדרך כלל סוד חתימה שהוחלף בצד אחד ועוד לא בצד השני, ולא סירוב קבוע. אילו המסירה נעצרה, תקלת תיאום של כמה דקות הייתה הופכת לאירועים חסרים. רק 410 Gone נחשב להודעה ברורה שהיעד לא רוצה יותר מסירות.

להתחיל למסור וובהוקים היום

מפנים את הוובהוקים ל-HookGet ורואים את המסירה הראשונה מגיעה, חתומה, תוך פחות מדקה.

פתיחת חשבון חינם לנסות את בודק הוובהוקים החינמי

10,000 מסירות בחודש בחינם, בלי כרטיס אשראי. המסלול החינמי חוסם ולא מחייב, כך שניסיון לא יכול להסתיים בחשבונית.