המלכודת במדריכי Backend
מדריכים מראים לכם תהליך פשוט. לקבל webhook. לעדכן את מסד הנתונים. להחזיר 200 OK.
הקוד שלכם עובד בבדיקות. אתם דוחפים אותו לסביבת הייצור (production). ואז אתם רואים רשומות כפולות במסד הנתונים שלכם. משתמשים מקבלים זיכוי כפול. רשומות נערמות.
מדריכים מתעלמים מהמציאות של כשלים ברשת.
הבעיה: רשתות לא אמינות
רשתות קורסות. השרת שלכם עשוי לעבד נתונים לאט. שגיאת DNS עלולה למנוע מתגובת ה-200 OK שלכם להגיע לשולח.
כששירות לא מקבל את האישור שלכם, הוא מבצע ניסיון חוזר (retry). הוא שולח את אותו ה-webhook שוב. אם הקוד שלכם מקבל כל בקשה, אתם יוצרים כפילויות.
הפתרון: אידמפוטנטיות (Idempotency)
אידמפוטנטיות פירושה שביצוע מספר בקשות זהות יניב את אותו אפקט כמו בקשה אחת בלבד.
חשבו על כפתור במעלית. לחיצה אחת על הכפתור לקומה 5 אומרת למעלית לאן ללכת. לחיצה עשר פעמים לא תשלח את המעלית לקומה 50. התוצאה נשארת זהה.
ה-webhook שלכם חייב לפעול כמו הכפתור הזה.
איך לתקן את זה
עקבו אחר הצעדים הבאים כדי לבנות webhooks בטוחים:
- מצאו את ה-ID הייחודי של האירוע.
- בדקו במסד הנתונים שלכם אם ה-ID הזה קיים לפני שאתם עושים משהו.
- אם ה-ID קיים, עצרו. החזירו 200 OK כדי שהשולח יפסיק לנסות שוב.
- אם ה-ID חדש, עבדו על הנתונים.
- שמרו את ה-ID של האירוע במסד הנתונים שלכם באופן מיידי.
דוגמה ללוגיקה ב-Node.js:
const eventId = req.body.event_id;
const existingEvent = await db.processedEvents.findUnique({
where: { id: eventId }
});
if (existingEvent) {
return res.status(200).send('Already processed');
}
await updateUserData(req.body.data);
await db.processedEvents.create({ data: { id: eventId } });
return res.status(200).send('Success');
בניית מערכות לתנאים מושלמים היא קלה. בניית מערכות להתמודדות עם כשלים היא הנדסה אמיתית.
האם התמודדתם עם נתונים כפולים כתוצאה מניסיונות חוזרים (retries)? איך אתם מטפלים באידמפוטנטיות?