4.5 KiB
4.5 KiB
Solution Design: natsClient_JS
1. Problem Decomposition
| Problem | Description | User Impact |
|---|---|---|
| P-001 | Consumers must manage a NATS connection lifecycle | Boilerplate, connection churn, dropped sockets |
| P-002 | Consumers must decode/encode payloads | Manual StringCodec/JSON in every call site |
| P-003 | Consumers need synchronous request/reply | Duplicated await-loop logic |
| P-004 | Consumers need a server-side reply handler | No way to serve requests from the client |
| P-005 | Consumers need msghandler envelope handling | Manual packing/unwrapping |
| P-006 | Consumers need to know connection state | No way to drive a status indicator |
| P-007 | Consumers need clean teardown | Leaked subscriptions and sockets |
2. Solution Approach
A single shared NATS connection exposed as ES module exports, with one helper function per
operation (subscribe, publish, request, reply, msghandler, close). Connection state flows into a
reactive Svelte store so consumers can bind it directly. Envelope packing delegates to
msghandler-csr.js, keeping this library focused on transport and lifecycle.
3. Decision Rationale
| Decision ID | Decision | Rationale | Alternatives Rejected |
|---|---|---|---|
| SD-001 | Shared module-level connection (nc) |
One socket serves every operation for the whole app | Per-call connect — connection churn |
| SD-002 | URL resolution precedence chain | Predictable, layered configuration (opts → env → config → default) | A single required URL arg — no env/config fallback |
| SD-003 | StringCodec + JSON.stringify/JSON.parse |
Uniform text encoding for both directions | Per-consumer encoding logic |
| SD-004 | Monitor nc.status() and nc.closed() |
Reactive connecting/connected/disconnected/error states |
Polling the connection |
| SD-005 | Subscription registry (Map) |
Centralized unsubscribe in closeNats |
Scattered subscriptions with no cleanup |
| SD-006 | Delegate msghandler to msghandler-csr.js |
Separation of envelope codec from transport | Reimplementing envelope logic here |
| SD-007 | Svelte store for connectionStatus |
Framework-agnostic consumers get reactivity for free | Plain variable consumers must wire their own subscription |
4. High-Level Component Diagram
C4 Level 2 - Container
%% C4 Level 2 - Container
flowchart LR
app[Consuming App<br/>Svelte app] -->|imports| natsClient[(natsClient.js)]
natsClient -->|nats.ws WSS| nats[(NATS broker)]
natsClient -->|smartpack/smartunpack| msg[(msghandler-csr.js)]
natsClient -->|writable| store[(connectionStatus store)]
Component Descriptions:
- natsClient.js: Shared connection + operation helpers (subscribe/publish/request/reply) +
status store + msghandler delegation.
- Links to requirements: FR-001..FR-008, NFR-101, NFR-201
- msghandler-csr.js: Envelope pack/unpack.
- Links to requirements: FR-006
- connectionStatus store: Reactive
{state, message}for the app.- Links to requirements: FR-007
5. Alternatives Considered
| Alternative | Pros | Cons | Decision |
|---|---|---|---|
| Per-call connection | Isolated lifecycle | Connection churn, re-auth overhead | Rejected — SD-001 |
| Manual decode at call site | No dependency | Duplicated error handling | Rejected — SD-003 |
| Callbacks instead of async iterators | Familiar | Verbose, harder to cancel | Rejected — uses for await |
6. Risk Assessment
| Risk | Impact | Probability | Mitigation |
|---|---|---|---|
| Broker unreachable at startup | Connection fails | Medium | getNats throws; consumer retries |
| Decode error on a message | Lost message / crash | Low | catch around decode/parse/handler |
| Reconnect never settles | Stuck disconnected |
Low | nc.status() + nc.closed() monitoring |
7. Requirements Traceability
| Solution Component | Requirement ID | Decision ID | Description |
|---|---|---|---|
| Shared connection | FR-001, FR-003 | SD-001 | One socket for pub/sub and publish |
| URL resolution | FR-001 | SD-002 | opts → env → config → default |
| Message decode | FR-002 | SD-003 | StringCodec + JSON/text fallback |
| Status tracking | FR-007 | SD-004 | status() + closed() monitor |
| Subscription cleanup | FR-008 | SD-005 | Map registry |
| msghandler | FR-006 | SD-006 | Delegation to msghandler-csr.js |
| Reactive status | NFR-201 | SD-007 | Svelte store |