Platform — Tổng quan
Platform là phần "nền" kỹ thuật chạy phía sau hậu trường: nó lắng nghe mọi thay đổi dữ liệu trong hệ thống rồi tự động kích hoạt các hệ quả — gửi thông báo, ghi lịch sử, lên lịch nhắc nhở — mà không cần mỗi tính năng tự viết lại.
Vấn đề Platform giải quyết
Tưởng tượng: khi một khách hàng đăng ký mới, hệ thống cần đồng thời (1) gửi email chào mừng, (2) ghi một dòng vào lịch sử của tài khoản đó. Nếu mỗi chỗ trong code tự làm hai việc này, sẽ xảy ra:
- Lặp code ở hàng chục nơi → dễ sai, dễ sót.
- Gửi trùng khi thao tác bị thử lại (retry) → khách nhận 2 email giống nhau.
- Khó mở rộng: thêm một loại thông báo mới phải sửa nhiều chỗ.
Platform gom các "hệ quả" này về một nơi xử lý chung, chạy nền, chống trùng lặp.
Ba mảnh ghép
| Mảnh | Một câu | Đọc sâu |
|---|---|---|
| ① Entity Event Flow | Khi một entity đổi, hệ thống phát một EntityEvent vào hàng đợi; worker đọc và định tuyến. | Kiến trúc |
| ② Notification Platform | Từ event (hoặc từ lệnh trực tiếp), tạo NotificationJob và đẩy qua pipeline gửi. | Kiến trúc |
| ③ Entity History | Từ event, ghi một dòng EntityHistory để dựng timeline audit cho entity. | Kiến trúc |
Một ý tưởng xuyên suốt: hybrid + chống trùng
Hai điều quan trọng nhất bạn cần nhớ về Platform:
- Hybrid (lai) — Có hai cách một thông báo được tạo ra: trực tiếp (service tự tạo) và qua event (service chỉ phát event, worker tạo). Cả hai dùng chung hạ tầng. Vì sao không ép về một cách? Xem Khái niệm.
- Chống trùng lặp bằng khóa tất định — Vì hàng đợi có thể giao một event nhiều lần, mọi hệ quả đều dùng deterministic key để "cùng sự kiện = cùng một dòng", retry không nhân đôi.
Implementation hiện tại
| Capability | Contract đang chạy |
|---|---|
| EntityEvent payload | Worker đo kích thước toàn bộ message đã serialize; message vượt khoảng 45 KiB được đưa payload không rỗng vào Blob và queue chỉ giữ BlobRef. |
| Notification traceability | SourceKey theo nguồn nghiệp vụ (ví dụ invoice/account) được giữ xuyên qua NotificationJob và OutgoingMessage; message được claim theo partition tất định và có lease/retry. |
| Ranh giới concern | Payload offload và traceability là hai concern độc lập; event thiếu payload/blob reference bắt buộc thì xử lý fail-closed. |
Ví dụ thực tế: Một event cập nhật invoice có payload lớn vẫn đi qua queue bằng
BlobRef, còn khi tra lịch sử gửi, support dùngSourceKey = invoice:{guid}để gom đúng các message của invoice đó.
Bạn nên đọc theo thứ tự
- Góc nhìn end-user — Platform "vô hình" với người dùng, nhưng nó là lý do họ nhận được email đúng lúc và thấy timeline lịch sử chính xác.
- Khái niệm cốt lõi — EntityEvent, hybrid, idempotency.
- Kiến trúc hệ thống — sơ đồ các thành phần & dòng dữ liệu.
- Luồng xử lý trong code — file, worker, class cụ thể.
- Lịch sử & quan sát — phân biệt run-history vs entity audit, tra cứu & observability.
- Dữ liệu & bảng đọc/ghi — entity nguồn, artifact ở Queue/Table/Blob theo luồng.
- Case thường gặp — thêm thông báo mới, xử lý retry, over-fire.