Database & lưu trữ
Hệ thống dùng bốn kho lưu trữ, mỗi kho cho một mục đích. Hiểu rõ "cái gì nằm ở đâu" giúp đọc mọi domain dễ hơn.
Bốn kho
| Kho | Dùng cho | Ví dụ |
|---|---|---|
| Azure SQL | Dữ liệu quan hệ, giao dịch | Subscription, Enrollment, Invoice, NotificationScheduler, AutomationScheduler, MessagingJob |
| Azure Table | Bản ghi key-value số lượng lớn, phân vùng | NotificationJob, OutgoingMessage, UserMessage, EntityHistory |
| Azure Blob | Payload/file lớn | snapshot history, payload campaign (messaging-job container) |
| Azure Queue | Vận chuyển event & việc nền | entity-event-queue |
PartitionKey / RowKey trong Azure Table
Mỗi dòng Table có cặp khóa (PartitionKey, RowKey) quyết định phân vùng và tra cứu. Triết lý chung của hệ thống:
- PartitionKey = nơi người dùng mong đợi mở lịch sử (vd entity của notification), không phải id nội bộ.
- RowKey ưu tiên tất định (suy từ danh tính sự kiện) để chống trùng khi retry; chỉ dùng GUID ngẫu nhiên cho flow action-derived không có danh tính ổn định.
Ví dụ (xem chi tiết ở Communication):
text
NotificationJob (event-derived): PartitionKey = entity.Guid ; RowKey = sentinel tất định
OutgoingMessage: PartitionKey = NotificationJob.RowKey
RowKey = {RecipientKeyHash}_{DeliveryMethod}
EntityHistory: RowKey = HistoryEventKey (tất định) + InsertOrReplaceQuy ước đặt tên (SQL)
| Quy ước | Ý nghĩa |
|---|---|
| PascalCase | Tên bảng/cột hiện hành. |
int + TypeId/StatusId | Enum/type/status (không dùng bit cho state mở rộng được). |
bit + Is/Has/Can/Allow | Chỉ dùng cho boolean thuần. |
*Date vs *DateTime | *Date = chỉ ngày; *DateTime = ngày + giờ. |
*On vs *At | *On = timestamp audit/lifecycle; *At = timestamp event/integration. |
*ById vs *By | *ById = FK/user id; *By = text hiển thị/nguồn/legacy. |
💡 Các quy ước này lý giải nhiều field bạn gặp:
CutOffMinute(int),TypeId=1(BillingOnly),Invoice.Date(date-only),CreatedOn(audit timestamp)…
Hai cơ chế lịch sử — đừng nhầm
EntityEventLog | EntityHistory | |
|---|---|---|
| Là gì | Audit thô của event | Projection lịch sử entity (timeline hiển thị) |
| Đường đọc | Khác | Khác |
| Gộp? | Không — vẫn là hai cơ chế tách biệt |
Ngoài ra Booking có BookingHistory riêng (không gộp vào EntityHistory).
Tiếp theo: Quy ước & nguyên tắc.