𝗖𝗮̣𝗺 𝗯𝗮̆́𝘆 𝘁𝗿𝗼𝗻𝗴 𝗰𝗮́𝗰 𝗯𝗮̀𝗶 𝗵𝘂̛𝗼̛́𝗻𝗴 𝗱𝗮̃𝗻 𝗕𝗮𝗰𝗸𝗲𝗻𝗱

Các bài hướng dẫn thường cho bạn thấy một quy trình đơn giản. Nhận một webhook. Cập nhật cơ sở dữ liệu. Trả về mã 200 OK.

Mã của bạn hoạt động tốt khi kiểm thử. Bạn đẩy nó lên môi trường production. Sau đó, bạn thấy các bản ghi bị trùng lặp trong cơ sở dữ liệu. Người dùng được cộng tiền hai lần. Các bản ghi dữ liệu bị dồn ứ lại.

Các bài hướng dẫn thường bỏ qua thực tế về lỗi mạng.

Vấn đề: Mạng không đáng tin cậy Mạng có thể gặp sự cố. Máy chủ của bạn có thể xử lý dữ liệu chậm. Một lỗi DNS có thể ngăn phản hồi 200 OK của bạn đến được phía người gửi.

Khi một dịch vụ không nhận được xác nhận từ bạn, nó sẽ thử lại. Nó gửi lại cùng một webhook đó. Nếu mã của bạn chấp nhận mọi yêu cầu, bạn sẽ tạo ra các bản ghi trùng lặp.

Giải pháp: Idempotency Idempotency có nghĩa là việc thực hiện nhiều yêu cầu giống hệt nhau sẽ mang lại kết quả tương tự như khi chỉ thực hiện một yêu cầu duy nhất.

Hãy nghĩ về nút bấm thang máy. Nhấn nút tầng 5 một lần sẽ cho thang máy biết cần đi đâu. Nhấn mười lần cũng không khiến thang máy chạy lên tầng 50. Kết quả vẫn không đổi.

Webhook của bạn phải hoạt động giống như nút bấm đó.

Cách khắc phục Hãy làm theo các bước sau để xây dựng các webhook an toàn:

  • Tìm ID duy nhất của sự kiện.
  • Kiểm tra ID đó trong cơ sở dữ liệu trước khi thực hiện bất kỳ thao tác nào.
  • Nếu ID đã tồn tại, hãy dừng lại. Trả về mã 200 OK để phía người gửi ngừng thử lại.
  • Nếu ID là mới, hãy xử lý dữ liệu.
  • Lưu ID sự kiện vào cơ sở dữ liệu của bạn ngay lập tức.

Ví dụ logic trong 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');

Xây dựng các hệ thống trong điều kiện hoàn hảo thì dễ. Xây dựng các hệ thống có khả năng chịu lỗi mới là kỹ thuật thực thụ.

Bạn đã bao giờ gặp phải tình trạng dữ liệu bị trùng lặp do các lần thử lại chưa? Bạn xử lý tính idempotency như thế nào?

Source: https://dev.to/anubhavg23/the-hidden-trap-in-backend-tutorials-why-your-webhooks-are-creating-duplicate-data-and-how-to-fix-dba