@horizon-republic/nestjs-jetstream 2.3.6 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -996
- package/dist/index.cjs +277 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +107 -26
- package/dist/index.d.ts +107 -26
- package/dist/index.js +283 -42
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ModuleMetadata, FactoryProvider, Type, Logger, OnApplicationShutdown, DynamicModule } from '@nestjs/common';
|
|
2
|
-
import { MsgHdrs, StreamConfig, ConsumerConfig, ConnectionOptions, NatsConnection, Status, JetStreamManager, ConsumerInfo, JsMsg, Msg } from 'nats';
|
|
2
|
+
import { MsgHdrs, StreamConfig, ConsumerConfig, DeliverPolicy, ReplayPolicy, ConnectionOptions, NatsConnection, Status, JetStreamManager, ConsumerInfo, JsMsg, Msg } from 'nats';
|
|
3
3
|
import { MessageHandler, Server, CustomTransportStrategy, ClientProxy, ReadPacket, WritePacket, BaseRpcContext } from '@nestjs/microservices';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
|
|
@@ -129,6 +129,37 @@ interface StreamConsumerOverrides {
|
|
|
129
129
|
stream?: Partial<StreamConfig>;
|
|
130
130
|
consumer?: Partial<ConsumerConfig>;
|
|
131
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Configuration for ordered event consumers.
|
|
134
|
+
*
|
|
135
|
+
* Ordered consumers use Limits retention and deliver messages in strict
|
|
136
|
+
* sequential order with at-most-once delivery. No ack/nak/DLQ.
|
|
137
|
+
*
|
|
138
|
+
* Only a subset of consumer options applies — ordered consumers are
|
|
139
|
+
* ephemeral and auto-managed by nats.js.
|
|
140
|
+
*/
|
|
141
|
+
interface OrderedEventOverrides {
|
|
142
|
+
/** Stream overrides (e.g. `max_age`, `max_bytes`). */
|
|
143
|
+
stream?: Partial<StreamConfig>;
|
|
144
|
+
/**
|
|
145
|
+
* Where to start reading when the consumer is (re)created.
|
|
146
|
+
* @default DeliverPolicy.All
|
|
147
|
+
*/
|
|
148
|
+
deliverPolicy?: DeliverPolicy;
|
|
149
|
+
/**
|
|
150
|
+
* Start sequence number. Only used when `deliverPolicy` is `StartSequence`.
|
|
151
|
+
*/
|
|
152
|
+
optStartSeq?: number;
|
|
153
|
+
/**
|
|
154
|
+
* Start time (ISO string). Only used when `deliverPolicy` is `StartTime`.
|
|
155
|
+
*/
|
|
156
|
+
optStartTime?: string;
|
|
157
|
+
/**
|
|
158
|
+
* Replay policy for historical messages.
|
|
159
|
+
* @default ReplayPolicy.Instant
|
|
160
|
+
*/
|
|
161
|
+
replayPolicy?: ReplayPolicy;
|
|
162
|
+
}
|
|
132
163
|
/**
|
|
133
164
|
* Root module configuration for `JetstreamModule.forRoot()`.
|
|
134
165
|
*
|
|
@@ -160,6 +191,15 @@ interface JetstreamModuleOptions {
|
|
|
160
191
|
events?: StreamConsumerOverrides;
|
|
161
192
|
/** Broadcast event stream/consumer overrides. */
|
|
162
193
|
broadcast?: StreamConsumerOverrides;
|
|
194
|
+
/**
|
|
195
|
+
* Ordered event consumer configuration.
|
|
196
|
+
*
|
|
197
|
+
* Ordered events use a separate stream with Limits retention and deliver
|
|
198
|
+
* messages in strict sequential order. Use `ordered:` prefix when publishing.
|
|
199
|
+
*
|
|
200
|
+
* @see OrderedEventOverrides
|
|
201
|
+
*/
|
|
202
|
+
ordered?: OrderedEventOverrides;
|
|
163
203
|
/**
|
|
164
204
|
* Transport lifecycle hook handlers.
|
|
165
205
|
* Unset hooks are silently ignored — no default logging.
|
|
@@ -244,8 +284,9 @@ type JetstreamModuleAsyncOptions = {
|
|
|
244
284
|
* - `'ev'` — Workqueue events (at-least-once delivery to one consumer).
|
|
245
285
|
* - `'cmd'` — RPC commands (JetStream mode only).
|
|
246
286
|
* - `'broadcast'` — Broadcast events (fan-out to all consumers).
|
|
287
|
+
* - `'ordered'` — Ordered events (strict sequential delivery, Limits retention).
|
|
247
288
|
*/
|
|
248
|
-
type StreamKind = 'ev' | 'cmd' | 'broadcast';
|
|
289
|
+
type StreamKind = 'ev' | 'cmd' | 'broadcast' | 'ordered';
|
|
249
290
|
|
|
250
291
|
/** @internal Grouped pattern lists by stream kind, used for stream/consumer setup. */
|
|
251
292
|
interface PatternsByKind {
|
|
@@ -255,6 +296,8 @@ interface PatternsByKind {
|
|
|
255
296
|
commands: string[];
|
|
256
297
|
/** Broadcast event patterns. */
|
|
257
298
|
broadcasts: string[];
|
|
299
|
+
/** Ordered event patterns (strict sequential delivery). */
|
|
300
|
+
ordered: string[];
|
|
258
301
|
}
|
|
259
302
|
|
|
260
303
|
/**
|
|
@@ -367,6 +410,10 @@ declare class PatternRegistry {
|
|
|
367
410
|
hasRpcHandlers(): boolean;
|
|
368
411
|
/** Check if any workqueue event handlers are registered. */
|
|
369
412
|
hasEventHandlers(): boolean;
|
|
413
|
+
/** Check if any ordered event handlers are registered. */
|
|
414
|
+
hasOrderedHandlers(): boolean;
|
|
415
|
+
/** Get fully-qualified NATS subjects for ordered handlers. */
|
|
416
|
+
getOrderedSubjects(): string[];
|
|
370
417
|
/** Get patterns grouped by kind. */
|
|
371
418
|
getPatternsByKind(): PatternsByKind;
|
|
372
419
|
/** Normalize a full NATS subject back to the user-facing pattern. */
|
|
@@ -449,21 +496,14 @@ interface DeadLetterConfig {
|
|
|
449
496
|
onDeadLetter(info: DeadLetterInfo): Promise<void>;
|
|
450
497
|
}
|
|
451
498
|
/**
|
|
452
|
-
* Routes incoming event messages (workqueue and
|
|
499
|
+
* Routes incoming event messages (workqueue, broadcast, and ordered) to NestJS handlers.
|
|
453
500
|
*
|
|
454
|
-
*
|
|
455
|
-
* -
|
|
456
|
-
* - Success -> ack (message consumed)
|
|
457
|
-
* - Handler error -> nak (NATS redelivers, up to `max_deliver` times)
|
|
458
|
-
* - Dead letter (max_deliver reached) -> onDeadLetter hook -> term or nak
|
|
459
|
-
* - Decode error -> term (no retry for malformed payloads)
|
|
460
|
-
* - No handler found -> term (configuration error)
|
|
501
|
+
* **Workqueue & Broadcast** — at-least-once delivery:
|
|
502
|
+
* - Success -> ack | Error -> nak (retry) | Dead letter -> term
|
|
461
503
|
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
* Handlers must be idempotent — NATS may redeliver on failure or timeout.
|
|
504
|
+
* **Ordered** — strict sequential delivery:
|
|
505
|
+
* - No ack/nak/DLQ — nats.js auto-acknowledges ordered consumer messages.
|
|
506
|
+
* - Handler errors are logged but do not affect delivery.
|
|
467
507
|
*/
|
|
468
508
|
declare class EventRouter {
|
|
469
509
|
private readonly messageProvider;
|
|
@@ -479,7 +519,7 @@ declare class EventRouter {
|
|
|
479
519
|
* Called after consumers are ensured so the DLQ map reflects reality.
|
|
480
520
|
*/
|
|
481
521
|
updateMaxDeliverMap(consumerMaxDelivers: Map<string, number>): void;
|
|
482
|
-
/** Start routing event and
|
|
522
|
+
/** Start routing event, broadcast, and ordered messages to handlers. */
|
|
483
523
|
start(): void;
|
|
484
524
|
/** Stop routing and unsubscribe from all streams. */
|
|
485
525
|
destroy(): void;
|
|
@@ -489,6 +529,8 @@ declare class EventRouter {
|
|
|
489
529
|
private handle;
|
|
490
530
|
/** Execute handler, then ack on success or nak/dead-letter on failure. */
|
|
491
531
|
private executeHandler;
|
|
532
|
+
/** Handle an ordered message: decode -> execute handler -> no ack/nak. */
|
|
533
|
+
private handleOrdered;
|
|
492
534
|
/** Check if the message has exhausted all delivery attempts. */
|
|
493
535
|
private isDeadLetter;
|
|
494
536
|
/** Handle a dead letter: invoke callback, then term or nak based on result. */
|
|
@@ -572,10 +614,13 @@ declare class MessageProvider {
|
|
|
572
614
|
private readonly eventBus;
|
|
573
615
|
private readonly logger;
|
|
574
616
|
private readonly activeIterators;
|
|
617
|
+
private orderedReadyResolve;
|
|
618
|
+
private orderedReadyReject;
|
|
575
619
|
private destroy$;
|
|
576
620
|
private eventMessages$;
|
|
577
621
|
private commandMessages$;
|
|
578
622
|
private broadcastMessages$;
|
|
623
|
+
private orderedMessages$;
|
|
579
624
|
constructor(connection: ConnectionProvider, eventBus: EventBus);
|
|
580
625
|
/** Observable stream of workqueue event messages. */
|
|
581
626
|
get events$(): Observable<JsMsg>;
|
|
@@ -583,6 +628,8 @@ declare class MessageProvider {
|
|
|
583
628
|
get commands$(): Observable<JsMsg>;
|
|
584
629
|
/** Observable stream of broadcast event messages. */
|
|
585
630
|
get broadcasts$(): Observable<JsMsg>;
|
|
631
|
+
/** Observable stream of ordered event messages (strict sequential delivery). */
|
|
632
|
+
get ordered$(): Observable<JsMsg>;
|
|
586
633
|
/**
|
|
587
634
|
* Start consuming messages from the given consumer infos.
|
|
588
635
|
*
|
|
@@ -590,6 +637,16 @@ declare class MessageProvider {
|
|
|
590
637
|
* Call `destroy()` to stop all consumers.
|
|
591
638
|
*/
|
|
592
639
|
start(consumers: Map<StreamKind, ConsumerInfo>): void;
|
|
640
|
+
/**
|
|
641
|
+
* Start an ordered consumer for strict sequential delivery.
|
|
642
|
+
*
|
|
643
|
+
* Unlike durable consumers, ordered consumers are ephemeral — created at
|
|
644
|
+
* consumption time, no durable state. nats.js handles auto-recreation.
|
|
645
|
+
*
|
|
646
|
+
* @param streamName - JetStream stream to consume from.
|
|
647
|
+
* @param filterSubjects - NATS subjects to filter on.
|
|
648
|
+
*/
|
|
649
|
+
startOrdered(streamName: string, filterSubjects: string[], orderedConfig?: OrderedEventOverrides): Promise<void>;
|
|
593
650
|
/** Stop all consumer flows and reinitialize subjects for potential restart. */
|
|
594
651
|
destroy(): void;
|
|
595
652
|
/** Create a self-healing consumer flow for a specific kind. */
|
|
@@ -598,6 +655,10 @@ declare class MessageProvider {
|
|
|
598
655
|
private consumeOnce;
|
|
599
656
|
/** Get the target subject for a consumer kind. */
|
|
600
657
|
private getTargetSubject;
|
|
658
|
+
/** Create a self-healing ordered consumer flow. */
|
|
659
|
+
private createOrderedFlow;
|
|
660
|
+
/** Single iteration: create ordered consumer -> iterate messages. */
|
|
661
|
+
private consumeOrderedOnce;
|
|
601
662
|
}
|
|
602
663
|
|
|
603
664
|
/**
|
|
@@ -648,8 +709,10 @@ declare class JetstreamStrategy extends Server implements CustomTransportStrateg
|
|
|
648
709
|
unwrap<T>(): T;
|
|
649
710
|
/** Access the pattern registry (for module-level introspection). */
|
|
650
711
|
getPatternRegistry(): PatternRegistry;
|
|
651
|
-
/** Determine which JetStream
|
|
712
|
+
/** Determine which JetStream streams are needed. */
|
|
652
713
|
private resolveStreamKinds;
|
|
714
|
+
/** Determine which stream kinds need durable consumers (ordered consumers are ephemeral). */
|
|
715
|
+
private resolveDurableConsumerKinds;
|
|
653
716
|
/** Build max_deliver map from actual NATS consumer configs (not options). */
|
|
654
717
|
private buildMaxDeliverMap;
|
|
655
718
|
private isCoreRpcMode;
|
|
@@ -831,7 +894,7 @@ declare class JetstreamClient extends ClientProxy {
|
|
|
831
894
|
private setupInbox;
|
|
832
895
|
/** Route an inbox reply to the matching pending callback. */
|
|
833
896
|
private routeInboxReply;
|
|
834
|
-
/** Build event subject — workqueue or
|
|
897
|
+
/** Build event subject — workqueue, broadcast, or ordered. */
|
|
835
898
|
private buildEventSubject;
|
|
836
899
|
/** Build NATS headers merging custom headers with transport headers. */
|
|
837
900
|
private buildHeaders;
|
|
@@ -865,13 +928,17 @@ declare class JetstreamRecord<TData = unknown> {
|
|
|
865
928
|
readonly headers: ReadonlyMap<string, string>;
|
|
866
929
|
/** Per-request RPC timeout override in ms. */
|
|
867
930
|
readonly timeout?: number | undefined;
|
|
931
|
+
/** Custom message ID for JetStream deduplication. */
|
|
932
|
+
readonly messageId?: string | undefined;
|
|
868
933
|
constructor(
|
|
869
934
|
/** Message payload. */
|
|
870
935
|
data: TData,
|
|
871
936
|
/** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */
|
|
872
937
|
headers: ReadonlyMap<string, string>,
|
|
873
938
|
/** Per-request RPC timeout override in ms. */
|
|
874
|
-
timeout?: number | undefined
|
|
939
|
+
timeout?: number | undefined,
|
|
940
|
+
/** Custom message ID for JetStream deduplication. */
|
|
941
|
+
messageId?: string | undefined);
|
|
875
942
|
}
|
|
876
943
|
/**
|
|
877
944
|
* Fluent builder for constructing JetstreamRecord instances.
|
|
@@ -883,6 +950,7 @@ declare class JetstreamRecordBuilder<TData = unknown> {
|
|
|
883
950
|
private data;
|
|
884
951
|
private readonly headers;
|
|
885
952
|
private timeout;
|
|
953
|
+
private messageId;
|
|
886
954
|
constructor(data?: TData);
|
|
887
955
|
/**
|
|
888
956
|
* Set the message payload.
|
|
@@ -905,6 +973,25 @@ declare class JetstreamRecordBuilder<TData = unknown> {
|
|
|
905
973
|
* @throws Error if any header name is reserved by the transport.
|
|
906
974
|
*/
|
|
907
975
|
setHeaders(headers: Record<string, string>): this;
|
|
976
|
+
/**
|
|
977
|
+
* Set a custom message ID for JetStream deduplication.
|
|
978
|
+
*
|
|
979
|
+
* NATS JetStream uses this ID to detect duplicate publishes within the
|
|
980
|
+
* stream's `duplicate_window`. If two messages with the same ID arrive
|
|
981
|
+
* within the window, the second is silently dropped.
|
|
982
|
+
*
|
|
983
|
+
* When not set, a random UUID is generated automatically.
|
|
984
|
+
*
|
|
985
|
+
* @param id - Unique message identifier (e.g. order ID, idempotency key).
|
|
986
|
+
*
|
|
987
|
+
* @example
|
|
988
|
+
* ```typescript
|
|
989
|
+
* new JetstreamRecordBuilder(data)
|
|
990
|
+
* .setMessageId(`order-${order.id}`)
|
|
991
|
+
* .build();
|
|
992
|
+
* ```
|
|
993
|
+
*/
|
|
994
|
+
setMessageId(id: string): this;
|
|
908
995
|
/**
|
|
909
996
|
* Set per-request RPC timeout.
|
|
910
997
|
*
|
|
@@ -1090,14 +1177,8 @@ declare enum JetstreamHeader {
|
|
|
1090
1177
|
Subject = "x-subject",
|
|
1091
1178
|
/** Internal name of the service that sent the message. */
|
|
1092
1179
|
CallerName = "x-caller-name",
|
|
1093
|
-
/** User-provided request ID (pass-through, not auto-generated). */
|
|
1094
|
-
RequestId = "x-request-id",
|
|
1095
|
-
/** User-provided trace ID for distributed tracing (pass-through). */
|
|
1096
|
-
TraceId = "x-trace-id",
|
|
1097
|
-
/** User-provided span ID for distributed tracing (pass-through). */
|
|
1098
|
-
SpanId = "x-span-id",
|
|
1099
1180
|
/** Set to `'true'` on error responses so the client can distinguish success from failure. */
|
|
1100
1181
|
Error = "x-error"
|
|
1101
1182
|
}
|
|
1102
1183
|
|
|
1103
|
-
export { type Codec, type DeadLetterInfo, EventBus, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, JetstreamRecord, JetstreamRecordBuilder, JetstreamStrategy, JsonCodec, type RpcConfig, RpcContext, type StreamConsumerOverrides, TransportEvent, type TransportHooks, getClientToken, nanos };
|
|
1184
|
+
export { type Codec, type DeadLetterInfo, EventBus, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, JetstreamRecord, JetstreamRecordBuilder, JetstreamStrategy, JsonCodec, type OrderedEventOverrides, type RpcConfig, RpcContext, type StreamConsumerOverrides, TransportEvent, type TransportHooks, getClientToken, nanos };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ModuleMetadata, FactoryProvider, Type, Logger, OnApplicationShutdown, DynamicModule } from '@nestjs/common';
|
|
2
|
-
import { MsgHdrs, StreamConfig, ConsumerConfig, ConnectionOptions, NatsConnection, Status, JetStreamManager, ConsumerInfo, JsMsg, Msg } from 'nats';
|
|
2
|
+
import { MsgHdrs, StreamConfig, ConsumerConfig, DeliverPolicy, ReplayPolicy, ConnectionOptions, NatsConnection, Status, JetStreamManager, ConsumerInfo, JsMsg, Msg } from 'nats';
|
|
3
3
|
import { MessageHandler, Server, CustomTransportStrategy, ClientProxy, ReadPacket, WritePacket, BaseRpcContext } from '@nestjs/microservices';
|
|
4
4
|
import { Observable } from 'rxjs';
|
|
5
5
|
|
|
@@ -129,6 +129,37 @@ interface StreamConsumerOverrides {
|
|
|
129
129
|
stream?: Partial<StreamConfig>;
|
|
130
130
|
consumer?: Partial<ConsumerConfig>;
|
|
131
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Configuration for ordered event consumers.
|
|
134
|
+
*
|
|
135
|
+
* Ordered consumers use Limits retention and deliver messages in strict
|
|
136
|
+
* sequential order with at-most-once delivery. No ack/nak/DLQ.
|
|
137
|
+
*
|
|
138
|
+
* Only a subset of consumer options applies — ordered consumers are
|
|
139
|
+
* ephemeral and auto-managed by nats.js.
|
|
140
|
+
*/
|
|
141
|
+
interface OrderedEventOverrides {
|
|
142
|
+
/** Stream overrides (e.g. `max_age`, `max_bytes`). */
|
|
143
|
+
stream?: Partial<StreamConfig>;
|
|
144
|
+
/**
|
|
145
|
+
* Where to start reading when the consumer is (re)created.
|
|
146
|
+
* @default DeliverPolicy.All
|
|
147
|
+
*/
|
|
148
|
+
deliverPolicy?: DeliverPolicy;
|
|
149
|
+
/**
|
|
150
|
+
* Start sequence number. Only used when `deliverPolicy` is `StartSequence`.
|
|
151
|
+
*/
|
|
152
|
+
optStartSeq?: number;
|
|
153
|
+
/**
|
|
154
|
+
* Start time (ISO string). Only used when `deliverPolicy` is `StartTime`.
|
|
155
|
+
*/
|
|
156
|
+
optStartTime?: string;
|
|
157
|
+
/**
|
|
158
|
+
* Replay policy for historical messages.
|
|
159
|
+
* @default ReplayPolicy.Instant
|
|
160
|
+
*/
|
|
161
|
+
replayPolicy?: ReplayPolicy;
|
|
162
|
+
}
|
|
132
163
|
/**
|
|
133
164
|
* Root module configuration for `JetstreamModule.forRoot()`.
|
|
134
165
|
*
|
|
@@ -160,6 +191,15 @@ interface JetstreamModuleOptions {
|
|
|
160
191
|
events?: StreamConsumerOverrides;
|
|
161
192
|
/** Broadcast event stream/consumer overrides. */
|
|
162
193
|
broadcast?: StreamConsumerOverrides;
|
|
194
|
+
/**
|
|
195
|
+
* Ordered event consumer configuration.
|
|
196
|
+
*
|
|
197
|
+
* Ordered events use a separate stream with Limits retention and deliver
|
|
198
|
+
* messages in strict sequential order. Use `ordered:` prefix when publishing.
|
|
199
|
+
*
|
|
200
|
+
* @see OrderedEventOverrides
|
|
201
|
+
*/
|
|
202
|
+
ordered?: OrderedEventOverrides;
|
|
163
203
|
/**
|
|
164
204
|
* Transport lifecycle hook handlers.
|
|
165
205
|
* Unset hooks are silently ignored — no default logging.
|
|
@@ -244,8 +284,9 @@ type JetstreamModuleAsyncOptions = {
|
|
|
244
284
|
* - `'ev'` — Workqueue events (at-least-once delivery to one consumer).
|
|
245
285
|
* - `'cmd'` — RPC commands (JetStream mode only).
|
|
246
286
|
* - `'broadcast'` — Broadcast events (fan-out to all consumers).
|
|
287
|
+
* - `'ordered'` — Ordered events (strict sequential delivery, Limits retention).
|
|
247
288
|
*/
|
|
248
|
-
type StreamKind = 'ev' | 'cmd' | 'broadcast';
|
|
289
|
+
type StreamKind = 'ev' | 'cmd' | 'broadcast' | 'ordered';
|
|
249
290
|
|
|
250
291
|
/** @internal Grouped pattern lists by stream kind, used for stream/consumer setup. */
|
|
251
292
|
interface PatternsByKind {
|
|
@@ -255,6 +296,8 @@ interface PatternsByKind {
|
|
|
255
296
|
commands: string[];
|
|
256
297
|
/** Broadcast event patterns. */
|
|
257
298
|
broadcasts: string[];
|
|
299
|
+
/** Ordered event patterns (strict sequential delivery). */
|
|
300
|
+
ordered: string[];
|
|
258
301
|
}
|
|
259
302
|
|
|
260
303
|
/**
|
|
@@ -367,6 +410,10 @@ declare class PatternRegistry {
|
|
|
367
410
|
hasRpcHandlers(): boolean;
|
|
368
411
|
/** Check if any workqueue event handlers are registered. */
|
|
369
412
|
hasEventHandlers(): boolean;
|
|
413
|
+
/** Check if any ordered event handlers are registered. */
|
|
414
|
+
hasOrderedHandlers(): boolean;
|
|
415
|
+
/** Get fully-qualified NATS subjects for ordered handlers. */
|
|
416
|
+
getOrderedSubjects(): string[];
|
|
370
417
|
/** Get patterns grouped by kind. */
|
|
371
418
|
getPatternsByKind(): PatternsByKind;
|
|
372
419
|
/** Normalize a full NATS subject back to the user-facing pattern. */
|
|
@@ -449,21 +496,14 @@ interface DeadLetterConfig {
|
|
|
449
496
|
onDeadLetter(info: DeadLetterInfo): Promise<void>;
|
|
450
497
|
}
|
|
451
498
|
/**
|
|
452
|
-
* Routes incoming event messages (workqueue and
|
|
499
|
+
* Routes incoming event messages (workqueue, broadcast, and ordered) to NestJS handlers.
|
|
453
500
|
*
|
|
454
|
-
*
|
|
455
|
-
* -
|
|
456
|
-
* - Success -> ack (message consumed)
|
|
457
|
-
* - Handler error -> nak (NATS redelivers, up to `max_deliver` times)
|
|
458
|
-
* - Dead letter (max_deliver reached) -> onDeadLetter hook -> term or nak
|
|
459
|
-
* - Decode error -> term (no retry for malformed payloads)
|
|
460
|
-
* - No handler found -> term (configuration error)
|
|
501
|
+
* **Workqueue & Broadcast** — at-least-once delivery:
|
|
502
|
+
* - Success -> ack | Error -> nak (retry) | Dead letter -> term
|
|
461
503
|
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
* Handlers must be idempotent — NATS may redeliver on failure or timeout.
|
|
504
|
+
* **Ordered** — strict sequential delivery:
|
|
505
|
+
* - No ack/nak/DLQ — nats.js auto-acknowledges ordered consumer messages.
|
|
506
|
+
* - Handler errors are logged but do not affect delivery.
|
|
467
507
|
*/
|
|
468
508
|
declare class EventRouter {
|
|
469
509
|
private readonly messageProvider;
|
|
@@ -479,7 +519,7 @@ declare class EventRouter {
|
|
|
479
519
|
* Called after consumers are ensured so the DLQ map reflects reality.
|
|
480
520
|
*/
|
|
481
521
|
updateMaxDeliverMap(consumerMaxDelivers: Map<string, number>): void;
|
|
482
|
-
/** Start routing event and
|
|
522
|
+
/** Start routing event, broadcast, and ordered messages to handlers. */
|
|
483
523
|
start(): void;
|
|
484
524
|
/** Stop routing and unsubscribe from all streams. */
|
|
485
525
|
destroy(): void;
|
|
@@ -489,6 +529,8 @@ declare class EventRouter {
|
|
|
489
529
|
private handle;
|
|
490
530
|
/** Execute handler, then ack on success or nak/dead-letter on failure. */
|
|
491
531
|
private executeHandler;
|
|
532
|
+
/** Handle an ordered message: decode -> execute handler -> no ack/nak. */
|
|
533
|
+
private handleOrdered;
|
|
492
534
|
/** Check if the message has exhausted all delivery attempts. */
|
|
493
535
|
private isDeadLetter;
|
|
494
536
|
/** Handle a dead letter: invoke callback, then term or nak based on result. */
|
|
@@ -572,10 +614,13 @@ declare class MessageProvider {
|
|
|
572
614
|
private readonly eventBus;
|
|
573
615
|
private readonly logger;
|
|
574
616
|
private readonly activeIterators;
|
|
617
|
+
private orderedReadyResolve;
|
|
618
|
+
private orderedReadyReject;
|
|
575
619
|
private destroy$;
|
|
576
620
|
private eventMessages$;
|
|
577
621
|
private commandMessages$;
|
|
578
622
|
private broadcastMessages$;
|
|
623
|
+
private orderedMessages$;
|
|
579
624
|
constructor(connection: ConnectionProvider, eventBus: EventBus);
|
|
580
625
|
/** Observable stream of workqueue event messages. */
|
|
581
626
|
get events$(): Observable<JsMsg>;
|
|
@@ -583,6 +628,8 @@ declare class MessageProvider {
|
|
|
583
628
|
get commands$(): Observable<JsMsg>;
|
|
584
629
|
/** Observable stream of broadcast event messages. */
|
|
585
630
|
get broadcasts$(): Observable<JsMsg>;
|
|
631
|
+
/** Observable stream of ordered event messages (strict sequential delivery). */
|
|
632
|
+
get ordered$(): Observable<JsMsg>;
|
|
586
633
|
/**
|
|
587
634
|
* Start consuming messages from the given consumer infos.
|
|
588
635
|
*
|
|
@@ -590,6 +637,16 @@ declare class MessageProvider {
|
|
|
590
637
|
* Call `destroy()` to stop all consumers.
|
|
591
638
|
*/
|
|
592
639
|
start(consumers: Map<StreamKind, ConsumerInfo>): void;
|
|
640
|
+
/**
|
|
641
|
+
* Start an ordered consumer for strict sequential delivery.
|
|
642
|
+
*
|
|
643
|
+
* Unlike durable consumers, ordered consumers are ephemeral — created at
|
|
644
|
+
* consumption time, no durable state. nats.js handles auto-recreation.
|
|
645
|
+
*
|
|
646
|
+
* @param streamName - JetStream stream to consume from.
|
|
647
|
+
* @param filterSubjects - NATS subjects to filter on.
|
|
648
|
+
*/
|
|
649
|
+
startOrdered(streamName: string, filterSubjects: string[], orderedConfig?: OrderedEventOverrides): Promise<void>;
|
|
593
650
|
/** Stop all consumer flows and reinitialize subjects for potential restart. */
|
|
594
651
|
destroy(): void;
|
|
595
652
|
/** Create a self-healing consumer flow for a specific kind. */
|
|
@@ -598,6 +655,10 @@ declare class MessageProvider {
|
|
|
598
655
|
private consumeOnce;
|
|
599
656
|
/** Get the target subject for a consumer kind. */
|
|
600
657
|
private getTargetSubject;
|
|
658
|
+
/** Create a self-healing ordered consumer flow. */
|
|
659
|
+
private createOrderedFlow;
|
|
660
|
+
/** Single iteration: create ordered consumer -> iterate messages. */
|
|
661
|
+
private consumeOrderedOnce;
|
|
601
662
|
}
|
|
602
663
|
|
|
603
664
|
/**
|
|
@@ -648,8 +709,10 @@ declare class JetstreamStrategy extends Server implements CustomTransportStrateg
|
|
|
648
709
|
unwrap<T>(): T;
|
|
649
710
|
/** Access the pattern registry (for module-level introspection). */
|
|
650
711
|
getPatternRegistry(): PatternRegistry;
|
|
651
|
-
/** Determine which JetStream
|
|
712
|
+
/** Determine which JetStream streams are needed. */
|
|
652
713
|
private resolveStreamKinds;
|
|
714
|
+
/** Determine which stream kinds need durable consumers (ordered consumers are ephemeral). */
|
|
715
|
+
private resolveDurableConsumerKinds;
|
|
653
716
|
/** Build max_deliver map from actual NATS consumer configs (not options). */
|
|
654
717
|
private buildMaxDeliverMap;
|
|
655
718
|
private isCoreRpcMode;
|
|
@@ -831,7 +894,7 @@ declare class JetstreamClient extends ClientProxy {
|
|
|
831
894
|
private setupInbox;
|
|
832
895
|
/** Route an inbox reply to the matching pending callback. */
|
|
833
896
|
private routeInboxReply;
|
|
834
|
-
/** Build event subject — workqueue or
|
|
897
|
+
/** Build event subject — workqueue, broadcast, or ordered. */
|
|
835
898
|
private buildEventSubject;
|
|
836
899
|
/** Build NATS headers merging custom headers with transport headers. */
|
|
837
900
|
private buildHeaders;
|
|
@@ -865,13 +928,17 @@ declare class JetstreamRecord<TData = unknown> {
|
|
|
865
928
|
readonly headers: ReadonlyMap<string, string>;
|
|
866
929
|
/** Per-request RPC timeout override in ms. */
|
|
867
930
|
readonly timeout?: number | undefined;
|
|
931
|
+
/** Custom message ID for JetStream deduplication. */
|
|
932
|
+
readonly messageId?: string | undefined;
|
|
868
933
|
constructor(
|
|
869
934
|
/** Message payload. */
|
|
870
935
|
data: TData,
|
|
871
936
|
/** Custom headers set via {@link JetstreamRecordBuilder.setHeader}. */
|
|
872
937
|
headers: ReadonlyMap<string, string>,
|
|
873
938
|
/** Per-request RPC timeout override in ms. */
|
|
874
|
-
timeout?: number | undefined
|
|
939
|
+
timeout?: number | undefined,
|
|
940
|
+
/** Custom message ID for JetStream deduplication. */
|
|
941
|
+
messageId?: string | undefined);
|
|
875
942
|
}
|
|
876
943
|
/**
|
|
877
944
|
* Fluent builder for constructing JetstreamRecord instances.
|
|
@@ -883,6 +950,7 @@ declare class JetstreamRecordBuilder<TData = unknown> {
|
|
|
883
950
|
private data;
|
|
884
951
|
private readonly headers;
|
|
885
952
|
private timeout;
|
|
953
|
+
private messageId;
|
|
886
954
|
constructor(data?: TData);
|
|
887
955
|
/**
|
|
888
956
|
* Set the message payload.
|
|
@@ -905,6 +973,25 @@ declare class JetstreamRecordBuilder<TData = unknown> {
|
|
|
905
973
|
* @throws Error if any header name is reserved by the transport.
|
|
906
974
|
*/
|
|
907
975
|
setHeaders(headers: Record<string, string>): this;
|
|
976
|
+
/**
|
|
977
|
+
* Set a custom message ID for JetStream deduplication.
|
|
978
|
+
*
|
|
979
|
+
* NATS JetStream uses this ID to detect duplicate publishes within the
|
|
980
|
+
* stream's `duplicate_window`. If two messages with the same ID arrive
|
|
981
|
+
* within the window, the second is silently dropped.
|
|
982
|
+
*
|
|
983
|
+
* When not set, a random UUID is generated automatically.
|
|
984
|
+
*
|
|
985
|
+
* @param id - Unique message identifier (e.g. order ID, idempotency key).
|
|
986
|
+
*
|
|
987
|
+
* @example
|
|
988
|
+
* ```typescript
|
|
989
|
+
* new JetstreamRecordBuilder(data)
|
|
990
|
+
* .setMessageId(`order-${order.id}`)
|
|
991
|
+
* .build();
|
|
992
|
+
* ```
|
|
993
|
+
*/
|
|
994
|
+
setMessageId(id: string): this;
|
|
908
995
|
/**
|
|
909
996
|
* Set per-request RPC timeout.
|
|
910
997
|
*
|
|
@@ -1090,14 +1177,8 @@ declare enum JetstreamHeader {
|
|
|
1090
1177
|
Subject = "x-subject",
|
|
1091
1178
|
/** Internal name of the service that sent the message. */
|
|
1092
1179
|
CallerName = "x-caller-name",
|
|
1093
|
-
/** User-provided request ID (pass-through, not auto-generated). */
|
|
1094
|
-
RequestId = "x-request-id",
|
|
1095
|
-
/** User-provided trace ID for distributed tracing (pass-through). */
|
|
1096
|
-
TraceId = "x-trace-id",
|
|
1097
|
-
/** User-provided span ID for distributed tracing (pass-through). */
|
|
1098
|
-
SpanId = "x-span-id",
|
|
1099
1180
|
/** Set to `'true'` on error responses so the client can distinguish success from failure. */
|
|
1100
1181
|
Error = "x-error"
|
|
1101
1182
|
}
|
|
1102
1183
|
|
|
1103
|
-
export { type Codec, type DeadLetterInfo, EventBus, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, JetstreamRecord, JetstreamRecordBuilder, JetstreamStrategy, JsonCodec, type RpcConfig, RpcContext, type StreamConsumerOverrides, TransportEvent, type TransportHooks, getClientToken, nanos };
|
|
1184
|
+
export { type Codec, type DeadLetterInfo, EventBus, JETSTREAM_CODEC, JETSTREAM_CONNECTION, JETSTREAM_EVENT_BUS, JETSTREAM_OPTIONS, JetstreamClient, type JetstreamFeatureOptions, JetstreamHeader, JetstreamHealthIndicator, type JetstreamHealthStatus, JetstreamModule, type JetstreamModuleAsyncOptions, type JetstreamModuleOptions, JetstreamRecord, JetstreamRecordBuilder, JetstreamStrategy, JsonCodec, type OrderedEventOverrides, type RpcConfig, RpcContext, type StreamConsumerOverrides, TransportEvent, type TransportHooks, getClientToken, nanos };
|