ADR-0002. Index Typesense phẳng do CDC điều khiển, lan toả thay đổi theo cascade
| Field | Value |
|---|---|
| Status | Accepted |
| Date | 2026-02-15 |
| Deciders | Phat Nguyen |
| Supersedes | - |
Bối cảnh
- Dữ liệu nguồn được chuẩn hoá rải rác trên nhiều bảng thuộc ba schema (
public,pricing,inventory); một product document cần các trường từ Product, ProductInfo, ProductCategory, MetaLink, FareSet/Fare, ProductBundler. - Document trong Typesense phải phẳng để truy vấn keyword và facet cho nhanh; trường
referencechỉ hỗ trợ một FK kiểu vô hướng duy nhất. - Một pipeline CDC Debezium → Kafka đã sẵn sàng phát luồng thay đổi từng dòng; search nên tiêu thụ luồng này thay vì hỏi vòng (poll) hay bị ghi đồng bộ.
- Một số bảng nguồn là principal của document (Product →
products); một số khác là bảng join/liên quan, chỉ làm thay đổi vài trường của một principal (ProductCategory ảnh hưởng tớicategoryIds).
Quyết định
Chúng tôi sẽ duy trì các document Typesense phẳng, được nạp dữ liệu qua CDC. TableToCollectionMap định tuyến các nguồn trực tiếp tới một collection thông qua entity mapper; các nguồn chỉ-cascade (bảng join/liên quan) được CDCCascadeService lan toả ra để tính lại các trường bị ảnh hưởng trên document principal, còn CDCEnrichmentService nạp thêm dữ liệu từ các collection khác. Sự an toàn khi sự kiện đến sai thứ tự đến từ các chốt bảo vệ LSN/version (source_lsn, deleted_at).
Hệ quả
| Ưu | Nhược |
|---|---|
| Truy vấn phẳng + facet nhanh, không cần join lúc runtime | Nhất quán cuối cùng (do CDC trễ) so với DB nguồn |
| Đồng bộ gần thời gian thực mà không cần ghi đồng bộ từ nguồn | Logic cascade phải biết mọi trường phụ thuộc của từng principal |
| Chốt LSN giúp việc phát lại / sự kiện sai thứ tự trở nên idempotent | Các trường phẳng (ví dụ tên parent, flags) có thể bị lệch và cần backfill/reindex |
| Một Kafka consumer phủ 18 topic trên 3 schema | Phụ thuộc vào quy ước đặt tên topic của Debezium + cấu hình connector |
Các phương án đã cân nhắc
| Phương án | Ưu | Nhược | Lý do loại bỏ |
|---|---|---|---|
| Join lúc truy vấn trong Typesense / ứng dụng | Luôn mới nhất | Chậm; reference giới hạn một FK vô hướng duy nhất | Phá hỏng mục đích của một search index |
| Ghi kép đồng bộ từ các service nguồn | Nhất quán tức thì | Gắn mọi nơi ghi với Typesense; rủi ro hỏng một phần | Mong manh; phát tán mối bận tâm về search ra khắp nơi |
| Reindex toàn bộ định kỳ từ DB | Đơn giản | Dữ liệu cũ giữa các lần chạy; tải nặng | Không đủ thời gian thực cho POS |
Tham chiếu
packages/search/src/common/kafka-topics.ts-TableToCollectionMap,ALL_CDC_TOPICS- API Events
- Domain Model