Architecture
@nx/searchlà một thư viện; nó không có runtime độc lập. Mọi sơ đồ thể hiện nó được nhúng trong process host (commerce).
1. System Context (C4 L1)
2. Container View (C4 L2)
3. Component View (C4 L3) - Phân lớp nội bộ
| Lớp | Trách nhiệm |
|---|---|
Mixin / SearchController | Bề mặt HTTP, kiểm soát auth + permission, gộp scope |
SearchService | Filter Ignis → tham số Typesense, phân giải include, định hình response |
TypesenseConverter | where/order/fields → filter_by/sort_by/include_fields |
| CDC services | Tiêu thụ, gom batch, định tuyến, cascade, bổ sung dữ liệu, lập index |
| Mappers | DB row (snake/camel) → Typesense doc; null cho dòng đã soft-delete |
CollectionRegistry | Registry singleton của 8 config (+ gắn embed.from) |
| Helpers | Typesense client, so sánh schema-drift, phân tích include |
4. Chỉ mục State Machine
Phần tử runtime có trạng thái duy nhất là CDC circuit breaker (tuỳ chọn bật).
| Phần tử | Trạng thái | Sơ đồ |
|---|---|---|
| CDC circuit breaker | CLOSED, OPEN | → nhảy tới |
CDC Circuit Breaker
| Từ | Sự kiện | Đến | Điều kiện |
|---|---|---|---|
CLOSED | probe sức khoẻ thất bại | OPEN | APP_ENV_CDC_CIRCUIT_BREAKER_ENABLED=true |
OPEN | probe phục hồi | CLOSED | hết cửa sổ tĩnh (Typesense 30s / Google 90s) |
OPEN | - | OPEN | giới hạn ở maxOpenMs (30 phút) |
Khi
OPEN, consumer tạm dừng (tắt auto-commit, nên offset không tiến) - message được đọc lại sau khi phục hồi.
5. Kịch bản Runtime
5.1 Query path (consumer → Typesense)
| Bước | Chi tiết |
|---|---|
| 2 | resolveSearchScope() chèn where theo tenant/merchant; mặc định null (mở) trừ khi host ghi đè |
| 5 | Nếu đặt disableSemanticSearch, trường embedding bị bỏ khỏi query_by (thuần từ khoá) |
| 7 | Quan hệ include được phân giải qua Typesense native join (reference) hoặc tra cứu bù dữ liệu |
5.2 CDC sync (Debezium → Typesense)
| Bước | Chi tiết |
|---|---|
| 3 | Batch được tinh chỉnh bởi CDCBatchingConfig (tối đa 200, flush 2000ms) + maxBytes 5MB |
| 5 | Mapper trả về null cho dòng đã soft-delete → kích hoạt lệnh xoá trên Typesense |
| 6 | Nguồn cascade: ProductCategory, MetaLink, FareSet/Fare, ProductBundler, hầu hết bảng inventory |
| 8 | Tắt auto-commit - offset chỉ tiến sau khi batch thành công (at-least-once) |
5.3 Schema-drift check khi bootstrap
Sai lệch được ghi log, không bao giờ tự áp dụng - việc tự dựng lại sẽ làm mất document. Dùng các script backfill cho thay đổi chỉ-thêm.
6. Các vấn đề xuyên suốt
| Vấn đề | Cách thư viện này xử lý |
|---|---|
| AuthN | Kế thừa từ host - SearchController + mixin nhận JWT hoặc Basic (AuthenticateStrategy.JWT, .BASIC) |
| AuthZ | Permission search:search / search:search-count; mixin yêu cầu config authorize từ consumer |
| Multi-tenancy | resolveSearchScope() chèn một scope where, gộp với filter của caller bằng and (host ghi đè theo từng entity) |
| i18n | { en, vi } được làm phẳng thành trường Typesense name.en / name.vi; locale tương lai được bắt bởi trường wildcard |
| Logging | Key-value có cấu trúc (key: %s) qua IGNIS logger |
| Idempotency | Bộ chặn LSN/version (source_lsn, deleted_at) loại bỏ event CDC sai thứ tự |
| Soft-delete | Mapper trả về null cho deletedAt != null → document bị xoá khỏi Typesense |
| Resilience | Circuit breaker (tuỳ chọn bật) + DLQ cho message lỗi + tiện ích thử lại |
| IDs | Document id = id dòng nguồn; thư viện không cấp Snowflake ID nào |