API Events
@nx/searchis a CDC consumer. It subscribes to 18 Debezium topics and produces only to a dead-letter queue. No outbound business events, no WebSocket, no BullMQ. Topic naming follows Debezium{prefix}.{schema}.{table}with prefixnx.seller.
1. Inbound — Kafka (CDC)
All topics defined in SearchCollections.CDC (src/common/kafka-topics.ts); the consumer subscribes to ALL_CDC_TOPICS. Handler is CDCService.handleBatch() for every topic.
Direct document sources (mapped in TableToCollectionMap)
| Topic | Schema.Table | → Collection |
|---|---|---|
nx.seller.public.Organizer | public.Organizer | organizers |
nx.seller.public.Merchant | public.Merchant | merchants |
nx.seller.public.Category | public.Category | categories |
nx.seller.public.Device | public.Device | devices |
nx.seller.public.SaleChannel | public.SaleChannel | sale-channels |
nx.seller.public.Product | public.Product | products |
nx.seller.public.ProductInfo | public.ProductInfo | products (i18n partial) |
nx.seller.public.ProductVariant | public.ProductVariant | product-variants |
nx.seller.inventory.InventoryStock | inventory.InventoryStock | inventories |
Cascade-only sources (not direct doc sources — fan out via CDCCascadeService)
| Topic | Schema.Table | Recomputes |
|---|---|---|
nx.seller.public.ProductCategory | public.ProductCategory | products + product-variants categoryIds |
nx.seller.public.MetaLink | public.MetaLink | product → variant productMetaLinks; variant metaLinks |
nx.seller.pricing.FareSet | pricing.FareSet | variant fareSet + defaultPrice |
nx.seller.pricing.Fare | pricing.Fare | variant fareSet + defaultPrice |
nx.seller.public.ProductBundler | public.ProductBundler | variant comboItems |
nx.seller.inventory.InventoryItem | inventory.InventoryItem | inventories item group |
nx.seller.inventory.InventoryLocation | inventory.InventoryLocation | inventories location group |
nx.seller.inventory.InventoryIdentifier | inventory.InventoryIdentifier | inventories identifiers[] |
nx.seller.inventory.Material | inventory.Material | inventories item (Material-typed) |
Debezium op codes
| Op | Meaning | Action |
|---|---|---|
c | create | upsert doc |
u | update | upsert doc |
d | delete | delete doc |
r | snapshot read | upsert doc (initial load) |
Any op where the mapper returns
null(soft-deleted) becomes a Typesense delete.
2. Outbound — Kafka
| Topic | Trigger | Consumers | Payload |
|---|---|---|---|
nx.seller.cdc.dlq (default, override via APP_ENV_CDC_DLQ_TOPIC) | A CDC message fails processing after retries | Ops / manual replay tooling | Original CDC message + failure metadata |
3. Inbound — BullMQ
N/A — no BullMQ consumer. (The selection report's embedding-queue design is a future option, not implemented.)
4. Outbound — BullMQ
N/A — no BullMQ producer.
5. WebSocket Emissions
N/A — the library emits no WebSocket events. Real-time UI updates are the host service's concern.
6. Payload Schemas
CDC payloads are Debezium envelopes, decoded with avsc. Search does not own these schemas — they mirror the source tables. Shape (abridged):
// Debezium change event (Avro-decoded)
interface DebeziumEnvelope<TBefore, TAfter> {
op: 'c' | 'u' | 'd' | 'r';
before: TBefore | null;
after: TAfter | null;
source: {
schema: string; // public | pricing | inventory
table: string; // e.g. "Product"
lsn: number; // → guards out-of-order replays (SearchVersionFields.SOURCE_LSN)
ts_ms: number;
};
}Search query params (consumer-facing, ISearchParams):
interface ISearchParams {
q?: string; // default '*'
limit?: number; // default 10, max 250
offset?: number;
where?: unknown; // Ignis-style → filter_by
order?: string | string[]; // "createdAt DESC" → sort_by
include?: IIncludeSpec[]; // relation hydration / native join
useCache?: boolean;
cacheTtl?: number;
disableSemanticSearch?: boolean; // drop embedding from query_by (strict keyword)
}7. Idempotency & Ordering
| Topic class | Delivery | Ordering | Recovery |
|---|---|---|---|
| All CDC topics | at-least-once (auto-commit off; commit after batch) | per-key via Debezium; LSN guard rejects stale events | re-read uncommitted offsets after restart / circuit-breaker close |
| DLQ | fire-and-forget | — | manual replay |
| Guard | Field | Effect |
|---|---|---|
| LSN | source_lsn (SearchVersionFields.SOURCE_LSN) | Skip event if its LSN ≤ stored doc LSN |
| Tombstone | deleted_at (SearchVersionFields.DELETED_AT) | Compared to keep deletes from being undone by stale upserts |