@amqp-contract/contract 0.9.0 → 0.11.0

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/dist/index.d.mts CHANGED
@@ -12,6 +12,66 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
12
12
  * @see https://github.com/standard-schema/standard-schema
13
13
  */
14
14
  type AnySchema = StandardSchemaV1;
15
+ /**
16
+ * TTL-Backoff retry options for exponential backoff with configurable delays.
17
+ *
18
+ * Uses TTL + wait queue pattern. Messages are published to a wait queue with
19
+ * per-message TTL, then dead-lettered back to the main queue after the TTL expires.
20
+ *
21
+ * **Benefits:** Configurable delays with exponential backoff and jitter.
22
+ * **Limitation:** More complex, potential head-of-queue blocking with mixed TTLs.
23
+ */
24
+ type TtlBackoffRetryOptions = {
25
+ /**
26
+ * TTL-Backoff mode uses wait queues with per-message TTL for exponential backoff.
27
+ */
28
+ mode: "ttl-backoff";
29
+ /**
30
+ * Maximum retry attempts before sending to DLQ.
31
+ * @default 3
32
+ */
33
+ maxRetries?: number;
34
+ /**
35
+ * Initial delay in ms before first retry.
36
+ * @default 1000
37
+ */
38
+ initialDelayMs?: number;
39
+ /**
40
+ * Maximum delay in ms between retries.
41
+ * @default 30000
42
+ */
43
+ maxDelayMs?: number;
44
+ /**
45
+ * Exponential backoff multiplier.
46
+ * @default 2
47
+ */
48
+ backoffMultiplier?: number;
49
+ /**
50
+ * Add jitter to prevent thundering herd.
51
+ * @default true
52
+ */
53
+ jitter?: boolean;
54
+ };
55
+ /**
56
+ * Quorum-Native retry options using RabbitMQ's native delivery limit feature.
57
+ *
58
+ * Uses quorum queue's `x-delivery-limit` feature. Messages are requeued immediately
59
+ * with `nack(requeue=true)`, and RabbitMQ tracks delivery count via `x-delivery-count`
60
+ * header. When the count exceeds the queue's `deliveryLimit`, the message is
61
+ * automatically dead-lettered.
62
+ *
63
+ * **Benefits:** Simpler architecture, no wait queues needed, no head-of-queue blocking.
64
+ * **Limitation:** Immediate retries only (no exponential backoff).
65
+ *
66
+ * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
67
+ */
68
+ type QuorumNativeRetryOptions = {
69
+ /**
70
+ * Quorum-Native mode uses RabbitMQ's native delivery limit feature.
71
+ * Requires the queue to be a quorum queue with `deliveryLimit` configured.
72
+ */
73
+ mode: "quorum-native";
74
+ };
15
75
  /**
16
76
  * Supported compression algorithms for message payloads.
17
77
  *
@@ -41,6 +101,225 @@ type AnySchema = StandardSchemaV1;
41
101
  * ```
42
102
  */
43
103
  type CompressionAlgorithm = "gzip" | "deflate";
104
+ /**
105
+ * Supported queue types in RabbitMQ.
106
+ *
107
+ * - `quorum`: Quorum queues (default, recommended) - Provide better durability and high-availability
108
+ * using the Raft consensus algorithm. Best for most production use cases.
109
+ * - `classic`: Classic queues - The traditional RabbitMQ queue type. Use only when you need
110
+ * specific features not supported by quorum queues (e.g., non-durable queues, priority queues).
111
+ *
112
+ * Note: Quorum queues require `durable: true` and do not support `exclusive: true`.
113
+ * When using quorum queues, `durable` is automatically set to `true`.
114
+ *
115
+ * @see https://www.rabbitmq.com/docs/quorum-queues
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * // Create a quorum queue (default, recommended)
120
+ * const orderQueue = defineQueue('order-processing', {
121
+ * type: 'quorum', // This is the default
122
+ * });
123
+ *
124
+ * // Create a classic queue (for special cases)
125
+ * const tempQueue = defineQueue('temp-queue', {
126
+ * type: 'classic',
127
+ * durable: false, // Only supported with classic queues
128
+ * });
129
+ * ```
130
+ */
131
+ type QueueType = "quorum" | "classic";
132
+ /**
133
+ * Common queue options shared between quorum and classic queues.
134
+ */
135
+ type BaseQueueOptions = {
136
+ /**
137
+ * If true, the queue survives broker restarts. Durable queues are persisted to disk.
138
+ * Note: Quorum queues are always durable regardless of this setting.
139
+ * @default false (but forced to true for quorum queues during setup)
140
+ */
141
+ durable?: boolean;
142
+ /**
143
+ * If true, the queue is deleted when the last consumer unsubscribes.
144
+ * @default false
145
+ */
146
+ autoDelete?: boolean;
147
+ /**
148
+ * Dead letter configuration for handling failed or rejected messages.
149
+ */
150
+ deadLetter?: DeadLetterConfig;
151
+ /**
152
+ * Additional AMQP arguments for advanced configuration.
153
+ */
154
+ arguments?: Record<string, unknown>;
155
+ };
156
+ /**
157
+ * Options for creating a quorum queue.
158
+ *
159
+ * Quorum queues do not support:
160
+ * - `exclusive` - Use classic queues for exclusive access
161
+ * - `maxPriority` - Use classic queues for priority queues
162
+ *
163
+ * Quorum queues provide native retry support via `deliveryLimit`:
164
+ * - RabbitMQ tracks delivery count automatically via `x-delivery-count` header
165
+ * - When the limit is exceeded, messages are dead-lettered (if DLX is configured)
166
+ * - This is simpler than TTL-based retry and avoids head-of-queue blocking issues
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const orderQueue = defineQueue('orders', {
171
+ * type: 'quorum',
172
+ * deadLetter: { exchange: dlx },
173
+ * deliveryLimit: 3, // Message dead-lettered after 3 delivery attempts
174
+ * });
175
+ * ```
176
+ */
177
+ type QuorumQueueOptions = BaseQueueOptions & {
178
+ /**
179
+ * Queue type: quorum (default, recommended)
180
+ */
181
+ type?: "quorum";
182
+ /**
183
+ * Quorum queues do not support exclusive mode.
184
+ * Use type: 'classic' if you need exclusive queues.
185
+ */
186
+ exclusive?: never;
187
+ /**
188
+ * Quorum queues do not support priority queues.
189
+ * Use type: 'classic' if you need priority queues.
190
+ */
191
+ maxPriority?: never;
192
+ /**
193
+ * Maximum number of delivery attempts before the message is dead-lettered.
194
+ *
195
+ * When a message is rejected (nacked) and requeued, RabbitMQ increments
196
+ * the `x-delivery-count` header. When this count reaches the delivery limit,
197
+ * the message is automatically dead-lettered (if DLX is configured) or dropped.
198
+ *
199
+ * This is a quorum queue-specific feature that provides native retry handling
200
+ * without the complexity of TTL-based wait queues.
201
+ *
202
+ * **Benefits over TTL-based retry:**
203
+ * - Simpler architecture (no wait queues needed)
204
+ * - No head-of-queue blocking issues (TTL only works at queue head)
205
+ * - Native RabbitMQ feature with atomic guarantees
206
+ *
207
+ * @minimum 1 - Must be a positive integer (1 or greater)
208
+ *
209
+ * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * const orderQueue = defineQueue('order-processing', {
214
+ * type: 'quorum',
215
+ * deliveryLimit: 5, // Allow up to 5 delivery attempts
216
+ * deadLetter: {
217
+ * exchange: dlx,
218
+ * routingKey: 'order.failed',
219
+ * },
220
+ * });
221
+ * ```
222
+ */
223
+ deliveryLimit?: number;
224
+ /**
225
+ * Retry configuration for handling failed message processing.
226
+ *
227
+ * Determines how the worker handles retries for consumers using this queue:
228
+ * - `"ttl-backoff"` (default): Uses wait queues with exponential backoff
229
+ * - `"quorum-native"`: Uses RabbitMQ's native delivery limit feature
230
+ *
231
+ * When using `"ttl-backoff"` mode, the core package will automatically create
232
+ * a wait queue (`{queueName}-wait`) and the necessary bindings.
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * // TTL-backoff mode with custom options
237
+ * const orderQueue = defineQueue('order-processing', {
238
+ * type: 'quorum',
239
+ * deadLetter: { exchange: dlx },
240
+ * retry: {
241
+ * mode: 'ttl-backoff',
242
+ * maxRetries: 5,
243
+ * initialDelayMs: 1000,
244
+ * maxDelayMs: 30000,
245
+ * },
246
+ * });
247
+ *
248
+ * // Quorum-native mode
249
+ * const orderQueue = defineQueue('order-processing', {
250
+ * type: 'quorum',
251
+ * deliveryLimit: 5,
252
+ * deadLetter: { exchange: dlx },
253
+ * retry: { mode: 'quorum-native' },
254
+ * });
255
+ * ```
256
+ */
257
+ retry?: TtlBackoffRetryOptions | QuorumNativeRetryOptions;
258
+ };
259
+ /**
260
+ * Options for creating a classic queue.
261
+ *
262
+ * Classic queues support all traditional RabbitMQ features including:
263
+ * - `exclusive: true` - For connection-scoped queues
264
+ * - `maxPriority` - For priority queues
265
+ * - `durable: false` - For non-durable queues
266
+ *
267
+ * @example
268
+ * ```typescript
269
+ * const priorityQueue = defineQueue('tasks', {
270
+ * type: 'classic',
271
+ * durable: true,
272
+ * maxPriority: 10,
273
+ * });
274
+ * ```
275
+ */
276
+ type ClassicQueueOptions = BaseQueueOptions & {
277
+ /**
278
+ * Queue type: classic (for special cases)
279
+ */
280
+ type: "classic";
281
+ /**
282
+ * If true, the queue can only be used by the declaring connection and is deleted when
283
+ * that connection closes. Exclusive queues are private to the connection.
284
+ * @default false
285
+ */
286
+ exclusive?: boolean;
287
+ /**
288
+ * Maximum priority level for priority queue (1-255, recommended: 1-10).
289
+ * Sets x-max-priority argument.
290
+ * Only supported with classic queues.
291
+ */
292
+ maxPriority?: number;
293
+ /**
294
+ * Retry configuration for handling failed message processing.
295
+ *
296
+ * Classic queues only support TTL-backoff retry mode, which uses wait queues
297
+ * with exponential backoff. For quorum-native retry, use quorum queues instead.
298
+ *
299
+ * @example
300
+ * ```typescript
301
+ * const orderQueue = defineQueue('order-processing', {
302
+ * type: 'classic',
303
+ * durable: true,
304
+ * deadLetter: { exchange: dlx },
305
+ * retry: {
306
+ * maxRetries: 5,
307
+ * initialDelayMs: 1000,
308
+ * maxDelayMs: 30000,
309
+ * },
310
+ * });
311
+ * ```
312
+ */
313
+ retry?: TtlBackoffRetryOptions;
314
+ };
315
+ /**
316
+ * Options for defining a queue. Uses a discriminated union based on the `type` property
317
+ * to enforce quorum queue constraints at compile time.
318
+ *
319
+ * - Quorum queues (default): Do not support `exclusive` or `maxPriority`
320
+ * - Classic queues: Support all options including `exclusive` and `maxPriority`
321
+ */
322
+ type DefineQueueOptions = QuorumQueueOptions | ClassicQueueOptions;
44
323
  /**
45
324
  * Base definition of an AMQP exchange.
46
325
  *
@@ -152,27 +431,19 @@ type DeadLetterConfig = {
152
431
  routingKey?: string;
153
432
  };
154
433
  /**
155
- * Definition of an AMQP queue.
156
- *
157
- * A queue stores messages until they are consumed by workers. Queues are bound to exchanges
158
- * to receive messages based on routing rules.
434
+ * Common properties shared by all queue definitions.
159
435
  */
160
- type QueueDefinition = {
436
+ type BaseQueueDefinition = {
161
437
  /**
162
438
  * The name of the queue. Must be unique within the RabbitMQ virtual host.
163
439
  */
164
440
  name: string;
165
441
  /**
166
442
  * If true, the queue survives broker restarts. Durable queues are persisted to disk.
167
- * @default false
443
+ * Note: Quorum queues are always durable regardless of this setting.
444
+ * @default false (but forced to true for quorum queues during setup)
168
445
  */
169
446
  durable?: boolean;
170
- /**
171
- * If true, the queue can only be used by the declaring connection and is deleted when
172
- * that connection closes. Exclusive queues are private to the connection.
173
- * @default false
174
- */
175
- exclusive?: boolean;
176
447
  /**
177
448
  * If true, the queue is deleted when the last consumer unsubscribes.
178
449
  * @default false
@@ -183,18 +454,6 @@ type QueueDefinition = {
183
454
  *
184
455
  * When configured, messages that are rejected, expire, or exceed queue limits
185
456
  * will be automatically forwarded to the specified dead letter exchange.
186
- *
187
- * @example
188
- * ```typescript
189
- * const dlx = defineExchange('orders-dlx', 'topic', { durable: true });
190
- * const queue = defineQueue('order-processing', {
191
- * durable: true,
192
- * deadLetter: {
193
- * exchange: dlx,
194
- * routingKey: 'order.failed'
195
- * }
196
- * });
197
- * ```
198
457
  */
199
458
  deadLetter?: DeadLetterConfig;
200
459
  /**
@@ -205,22 +464,143 @@ type QueueDefinition = {
205
464
  * - `x-expires`: Queue expiration time in milliseconds
206
465
  * - `x-max-length`: Maximum number of messages in the queue
207
466
  * - `x-max-length-bytes`: Maximum size of the queue in bytes
208
- * - `x-max-priority`: Maximum priority level for priority queues
467
+ */
468
+ arguments?: Record<string, unknown>;
469
+ };
470
+ /**
471
+ * Definition of a quorum queue.
472
+ *
473
+ * Quorum queues provide better durability and high-availability using the Raft consensus algorithm.
474
+ * They support native retry handling via `deliveryLimit` and both TTL-backoff and quorum-native retry modes.
475
+ */
476
+ type QuorumQueueDefinition = BaseQueueDefinition & {
477
+ /**
478
+ * Queue type discriminator: quorum queue.
479
+ */
480
+ type: "quorum";
481
+ /**
482
+ * Quorum queues do not support exclusive mode.
483
+ * Use type: 'classic' if you need exclusive queues.
484
+ */
485
+ exclusive?: never;
486
+ /**
487
+ * Quorum queues do not support priority queues.
488
+ * Use type: 'classic' if you need priority queues.
489
+ */
490
+ maxPriority?: never;
491
+ /**
492
+ * Maximum number of delivery attempts before the message is dead-lettered.
209
493
  *
210
- * Note: When using the `deadLetter` property, the `x-dead-letter-exchange` and
211
- * `x-dead-letter-routing-key` arguments are automatically set and should not be
212
- * specified in this arguments object.
494
+ * This is a quorum queue-specific feature. When a message is rejected (nacked)
495
+ * and requeued, RabbitMQ increments the `x-delivery-count` header. When this
496
+ * count reaches the delivery limit, the message is automatically dead-lettered
497
+ * (if DLX is configured) or dropped.
213
498
  *
214
- * @example
215
- * ```typescript
216
- * {
217
- * 'x-message-ttl': 86400000, // 24 hours
218
- * 'x-max-priority': 10
219
- * }
220
- * ```
499
+ * @minimum 1 - Must be a positive integer (1 or greater)
500
+ *
501
+ * @see https://www.rabbitmq.com/docs/quorum-queues#poison-message-handling
221
502
  */
222
- arguments?: Record<string, unknown>;
503
+ deliveryLimit?: number;
504
+ /**
505
+ * Retry configuration for handling failed message processing.
506
+ *
507
+ * Quorum queues support both:
508
+ * - `ttl-backoff`: Uses wait queues with exponential backoff
509
+ * - `quorum-native`: Uses RabbitMQ's native delivery limit feature
510
+ */
511
+ retry?: TtlBackoffRetryOptions | QuorumNativeRetryOptions;
512
+ };
513
+ /**
514
+ * Definition of a classic queue.
515
+ *
516
+ * Classic queues are the traditional RabbitMQ queue type. Use them when you need
517
+ * specific features not supported by quorum queues (e.g., exclusive queues, priority queues).
518
+ */
519
+ type ClassicQueueDefinition = BaseQueueDefinition & {
520
+ /**
521
+ * Queue type discriminator: classic queue.
522
+ */
523
+ type: "classic";
524
+ /**
525
+ * Classic queues do not support delivery limits.
526
+ * Use type: 'quorum' if you need native retry with delivery limits.
527
+ */
528
+ deliveryLimit?: never;
529
+ /**
530
+ * If true, the queue can only be used by the declaring connection and is deleted when
531
+ * that connection closes. Exclusive queues are private to the connection.
532
+ * @default false
533
+ */
534
+ exclusive?: boolean;
535
+ /**
536
+ * Retry configuration for handling failed message processing.
537
+ *
538
+ * Classic queues only support TTL-backoff retry mode.
539
+ */
540
+ retry?: TtlBackoffRetryOptions;
541
+ };
542
+ /**
543
+ * Definition of an AMQP queue.
544
+ *
545
+ * A discriminated union based on queue type:
546
+ * - `QuorumQueueDefinition`: For quorum queues (type: "quorum")
547
+ * - `ClassicQueueDefinition`: For classic queues (type: "classic")
548
+ *
549
+ * Use `queue.type` as the discriminator to narrow the type.
550
+ */
551
+ type QueueDefinition = QuorumQueueDefinition | ClassicQueueDefinition;
552
+ /**
553
+ * A queue with automatically generated TTL-backoff retry infrastructure.
554
+ *
555
+ * This type is returned by `defineQueue` when TTL-backoff retry is configured
556
+ * with a dead letter exchange. When passed to `defineContract`, the wait queue
557
+ * and bindings are automatically added to the contract.
558
+ *
559
+ * @example
560
+ * ```typescript
561
+ * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
562
+ * const queue = defineQueue('order-processing', {
563
+ * deadLetter: { exchange: dlx },
564
+ * retry: { mode: 'ttl-backoff', maxRetries: 5 },
565
+ * });
566
+ * // queue is QueueWithTtlBackoffInfrastructure
567
+ *
568
+ * const contract = defineContract({
569
+ * exchanges: { dlx },
570
+ * queues: { orderProcessing: queue }, // Automatically adds wait queue
571
+ * // ... bindings are automatically generated
572
+ * });
573
+ * ```
574
+ */
575
+ type QueueWithTtlBackoffInfrastructure = {
576
+ /**
577
+ * Discriminator to identify this as a queue with TTL-backoff infrastructure.
578
+ * @internal
579
+ */
580
+ __brand: "QueueWithTtlBackoffInfrastructure";
581
+ /**
582
+ * The main queue definition.
583
+ */
584
+ queue: QueueDefinition;
585
+ /**
586
+ * The wait queue for holding messages during backoff delay.
587
+ */
588
+ waitQueue: QueueDefinition;
589
+ /**
590
+ * Binding that routes failed messages to the wait queue.
591
+ */
592
+ waitQueueBinding: QueueBindingDefinition;
593
+ /**
594
+ * Binding that routes retried messages back to the main queue.
595
+ */
596
+ mainQueueRetryBinding: QueueBindingDefinition;
223
597
  };
598
+ /**
599
+ * A queue entry that can be passed to `defineContract`.
600
+ *
601
+ * Can be either a plain queue definition or a queue with TTL-backoff infrastructure.
602
+ */
603
+ type QueueEntry = QueueDefinition | QueueWithTtlBackoffInfrastructure;
224
604
  /**
225
605
  * Definition of a message with typed payload and optional headers.
226
606
  *
@@ -432,8 +812,11 @@ type ContractDefinition = {
432
812
  /**
433
813
  * Named queue definitions.
434
814
  * Each key becomes available as a named resource in the contract.
815
+ *
816
+ * When a queue has TTL-backoff retry configured, pass the `QueueWithTtlBackoffInfrastructure`
817
+ * object returned by `defineQueue`. The wait queue and bindings will be automatically added.
435
818
  */
436
- queues?: Record<string, QueueDefinition>;
819
+ queues?: Record<string, QueueEntry>;
437
820
  /**
438
821
  * Named binding definitions.
439
822
  * Bindings can be queue-to-exchange or exchange-to-exchange.
@@ -562,33 +945,30 @@ declare function defineExchange(name: string, type: "topic", options?: Omit<Base
562
945
  * A queue stores messages until they are consumed by workers. Queues can be bound to exchanges
563
946
  * to receive messages based on routing rules.
564
947
  *
948
+ * By default, queues are created as quorum queues which provide better durability and
949
+ * high-availability. Use `type: 'classic'` for special cases like non-durable queues
950
+ * or priority queues.
951
+ *
565
952
  * @param name - The name of the queue
566
953
  * @param options - Optional queue configuration
567
- * @param options.durable - If true, the queue survives broker restarts (default: false)
568
- * @param options.exclusive - If true, the queue can only be used by the declaring connection (default: false)
954
+ * @param options.type - Queue type: 'quorum' (default, recommended) or 'classic'
955
+ * @param options.durable - If true, the queue survives broker restarts. Quorum queues are always durable.
956
+ * @param options.exclusive - If true, the queue can only be used by the declaring connection. Only supported with classic queues.
569
957
  * @param options.autoDelete - If true, the queue is deleted when the last consumer unsubscribes (default: false)
570
958
  * @param options.deadLetter - Dead letter configuration for handling failed messages
571
- * @param options.maxPriority - Maximum priority level for priority queue (1-255, recommended: 1-10). Sets x-max-priority argument.
959
+ * @param options.maxPriority - Maximum priority level for priority queue (1-255, recommended: 1-10). Only supported with classic queues.
572
960
  * @param options.arguments - Additional AMQP arguments (e.g., x-message-ttl)
573
961
  * @returns A queue definition
574
962
  *
575
963
  * @example
576
964
  * ```typescript
577
- * // Basic queue
578
- * const orderQueue = defineQueue('order-processing', {
579
- * durable: true,
580
- * });
965
+ * // Quorum queue (default, recommended for production)
966
+ * const orderQueue = defineQueue('order-processing');
581
967
  *
582
- * // Priority queue with max priority of 10
583
- * const taskQueue = defineQueue('urgent-tasks', {
584
- * durable: true,
585
- * maxPriority: 10,
586
- * });
587
- *
588
- * // Queue with dead letter exchange
968
+ * // Explicit quorum queue with dead letter exchange
589
969
  * const dlx = defineExchange('orders-dlx', 'topic', { durable: true });
590
970
  * const orderQueueWithDLX = defineQueue('order-processing', {
591
- * durable: true,
971
+ * type: 'quorum',
592
972
  * deadLetter: {
593
973
  * exchange: dlx,
594
974
  * routingKey: 'order.failed'
@@ -597,11 +977,31 @@ declare function defineExchange(name: string, type: "topic", options?: Omit<Base
597
977
  * 'x-message-ttl': 86400000, // 24 hours
598
978
  * }
599
979
  * });
980
+ *
981
+ * // Classic queue (for special cases)
982
+ * const tempQueue = defineQueue('temp-queue', {
983
+ * type: 'classic',
984
+ * durable: false,
985
+ * autoDelete: true,
986
+ * });
987
+ *
988
+ * // Priority queue (requires classic type)
989
+ * const taskQueue = defineQueue('urgent-tasks', {
990
+ * type: 'classic',
991
+ * durable: true,
992
+ * maxPriority: 10,
993
+ * });
994
+ *
995
+ * // Queue with TTL-backoff retry (returns infrastructure automatically)
996
+ * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
997
+ * const orderQueue = defineQueue('order-processing', {
998
+ * deadLetter: { exchange: dlx },
999
+ * retry: { mode: 'ttl-backoff', maxRetries: 5 },
1000
+ * });
1001
+ * // orderQueue is QueueWithTtlBackoffInfrastructure, pass directly to defineContract
600
1002
  * ```
601
1003
  */
602
- declare function defineQueue(name: string, options?: Omit<QueueDefinition, "name"> & {
603
- maxPriority?: number;
604
- }): QueueDefinition;
1004
+ declare function defineQueue(name: string, options?: DefineQueueOptions): QueueDefinition | QueueWithTtlBackoffInfrastructure;
605
1005
  /**
606
1006
  * Define a message definition with payload and optional headers/metadata.
607
1007
  *
@@ -648,7 +1048,7 @@ declare function defineMessage<TPayload extends MessageDefinition["payload"], TH
648
1048
  * Binds a queue to a fanout exchange to receive all messages published to the exchange.
649
1049
  * Fanout exchanges ignore routing keys, so this overload doesn't require one.
650
1050
  *
651
- * @param queue - The queue definition to bind
1051
+ * @param queue - The queue definition or queue with infrastructure to bind
652
1052
  * @param exchange - The fanout exchange definition
653
1053
  * @param options - Optional binding configuration
654
1054
  * @param options.arguments - Additional AMQP arguments for the binding
@@ -662,7 +1062,7 @@ declare function defineMessage<TPayload extends MessageDefinition["payload"], TH
662
1062
  * const binding = defineQueueBinding(logsQueue, logsExchange);
663
1063
  * ```
664
1064
  */
665
- declare function defineQueueBinding(queue: QueueDefinition, exchange: FanoutExchangeDefinition, options?: Omit<Extract<QueueBindingDefinition, {
1065
+ declare function defineQueueBinding(queue: QueueEntry, exchange: FanoutExchangeDefinition, options?: Omit<Extract<QueueBindingDefinition, {
666
1066
  exchange: FanoutExchangeDefinition;
667
1067
  }>, "type" | "queue" | "exchange" | "routingKey">): Extract<QueueBindingDefinition, {
668
1068
  exchange: FanoutExchangeDefinition;
@@ -678,7 +1078,7 @@ declare function defineQueueBinding(queue: QueueDefinition, exchange: FanoutExch
678
1078
  * - `*` matches exactly one word
679
1079
  * - `#` matches zero or more words
680
1080
  *
681
- * @param queue - The queue definition to bind
1081
+ * @param queue - The queue definition or queue with infrastructure to bind
682
1082
  * @param exchange - The direct or topic exchange definition
683
1083
  * @param options - Binding configuration (routingKey is required)
684
1084
  * @param options.routingKey - The routing key pattern for message routing
@@ -701,7 +1101,7 @@ declare function defineQueueBinding(queue: QueueDefinition, exchange: FanoutExch
701
1101
  * });
702
1102
  * ```
703
1103
  */
704
- declare function defineQueueBinding(queue: QueueDefinition, exchange: DirectExchangeDefinition | TopicExchangeDefinition, options: Omit<Extract<QueueBindingDefinition, {
1104
+ declare function defineQueueBinding(queue: QueueEntry, exchange: DirectExchangeDefinition | TopicExchangeDefinition, options: Omit<Extract<QueueBindingDefinition, {
705
1105
  exchange: DirectExchangeDefinition | TopicExchangeDefinition;
706
1106
  }>, "type" | "queue" | "exchange">): Extract<QueueBindingDefinition, {
707
1107
  exchange: DirectExchangeDefinition | TopicExchangeDefinition;
@@ -877,7 +1277,7 @@ declare function definePublisher<TMessage extends MessageDefinition>(exchange: D
877
1277
  * // });
878
1278
  * ```
879
1279
  */
880
- declare function defineConsumer<TMessage extends MessageDefinition>(queue: QueueDefinition, message: TMessage, options?: Omit<ConsumerDefinition<TMessage>, "queue" | "message">): ConsumerDefinition<TMessage>;
1280
+ declare function defineConsumer<TMessage extends MessageDefinition>(queue: QueueEntry, message: TMessage, options?: Omit<ConsumerDefinition<TMessage>, "queue" | "message">): ConsumerDefinition<TMessage>;
881
1281
  /**
882
1282
  * Define an AMQP contract.
883
1283
  *
@@ -948,6 +1348,21 @@ declare function defineConsumer<TMessage extends MessageDefinition>(queue: Queue
948
1348
  * ```
949
1349
  */
950
1350
  declare function defineContract<TContract extends ContractDefinition>(definition: TContract): TContract;
1351
+ /**
1352
+ * Extract the plain QueueDefinition from a QueueEntry.
1353
+ * If the entry is a QueueWithTtlBackoffInfrastructure, returns the inner queue.
1354
+ * Otherwise, returns the entry as-is.
1355
+ *
1356
+ * @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
1357
+ * @returns The plain QueueDefinition
1358
+ *
1359
+ * @example
1360
+ * ```typescript
1361
+ * const queue = defineQueue('orders', { retry: { mode: 'ttl-backoff' }, deadLetter: { exchange: dlx } });
1362
+ * const plainQueue = extractQueue(queue); // Returns the inner QueueDefinition
1363
+ * ```
1364
+ */
1365
+ declare function extractQueue(entry: QueueEntry): QueueDefinition;
951
1366
  /**
952
1367
  * Publisher-first builder result for fanout and direct exchanges.
953
1368
  *
@@ -968,10 +1383,10 @@ type PublisherFirstResult<TMessage extends MessageDefinition, TPublisher extends
968
1383
  * The consumer will automatically use the same message schema and
969
1384
  * a binding will be created with the same routing key.
970
1385
  *
971
- * @param queue - The queue that will consume the messages
1386
+ * @param queue - The queue (or queue with infrastructure) that will consume the messages
972
1387
  * @returns An object with the consumer definition and binding
973
1388
  */
974
- createConsumer: (queue: QueueDefinition) => {
1389
+ createConsumer: (queue: QueueEntry) => {
975
1390
  consumer: ConsumerDefinition<TMessage>;
976
1391
  binding: QueueBindingDefinition;
977
1392
  };
@@ -1069,11 +1484,11 @@ type PublisherFirstResultWithRoutingKey<TMessage extends MessageDefinition, TPub
1069
1484
  * Create a consumer that receives messages from this publisher.
1070
1485
  * For topic exchanges, the routing key pattern can be specified for the binding.
1071
1486
  *
1072
- * @param queue - The queue that will consume the messages
1487
+ * @param queue - The queue (or queue with infrastructure) that will consume the messages
1073
1488
  * @param routingKey - Optional routing key pattern for the binding (defaults to publisher's routing key)
1074
1489
  * @returns An object with the consumer definition and binding
1075
1490
  */
1076
- createConsumer: <TConsumerRoutingKey extends string = TRoutingKey>(queue: QueueDefinition, routingKey?: BindingPattern<TConsumerRoutingKey>) => {
1491
+ createConsumer: <TConsumerRoutingKey extends string = TRoutingKey>(queue: QueueEntry, routingKey?: BindingPattern<TConsumerRoutingKey>) => {
1077
1492
  consumer: ConsumerDefinition<TMessage>;
1078
1493
  binding: QueueBindingDefinition;
1079
1494
  };
@@ -1357,7 +1772,7 @@ type ConsumerFirstResultWithRoutingKey<TMessage extends MessageDefinition, TCons
1357
1772
  * });
1358
1773
  * ```
1359
1774
  */
1360
- declare function defineConsumerFirst<TMessage extends MessageDefinition>(queue: QueueDefinition, exchange: FanoutExchangeDefinition, message: TMessage, options?: Omit<Extract<QueueBindingDefinition, {
1775
+ declare function defineConsumerFirst<TMessage extends MessageDefinition>(queue: QueueEntry, exchange: FanoutExchangeDefinition, message: TMessage, options?: Omit<Extract<QueueBindingDefinition, {
1361
1776
  exchange: FanoutExchangeDefinition;
1362
1777
  }>, "type" | "queue" | "exchange" | "routingKey">): ConsumerFirstResult<TMessage, ConsumerDefinition<TMessage>, Extract<QueueBindingDefinition, {
1363
1778
  exchange: FanoutExchangeDefinition;
@@ -1411,7 +1826,7 @@ declare function defineConsumerFirst<TMessage extends MessageDefinition>(queue:
1411
1826
  * });
1412
1827
  * ```
1413
1828
  */
1414
- declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueDefinition, exchange: DirectExchangeDefinition, message: TMessage, options: {
1829
+ declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueEntry, exchange: DirectExchangeDefinition, message: TMessage, options: {
1415
1830
  routingKey: RoutingKey<TRoutingKey>;
1416
1831
  arguments?: Record<string, unknown>;
1417
1832
  }): ConsumerFirstResult<TMessage, ConsumerDefinition<TMessage>, Extract<QueueBindingDefinition, {
@@ -1469,12 +1884,85 @@ declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutin
1469
1884
  * });
1470
1885
  * ```
1471
1886
  */
1472
- declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueDefinition, exchange: TopicExchangeDefinition, message: TMessage, options: {
1887
+ declare function defineConsumerFirst<TMessage extends MessageDefinition, TRoutingKey extends string>(queue: QueueEntry, exchange: TopicExchangeDefinition, message: TMessage, options: {
1473
1888
  routingKey: BindingPattern<TRoutingKey>;
1474
1889
  arguments?: Record<string, unknown>;
1475
1890
  }): ConsumerFirstResultWithRoutingKey<TMessage, ConsumerDefinition<TMessage>, Extract<QueueBindingDefinition, {
1476
1891
  exchange: TopicExchangeDefinition;
1477
1892
  }>>;
1893
+ /**
1894
+ * Result type for TTL-backoff retry infrastructure builder.
1895
+ *
1896
+ * Contains the wait queue and bindings needed for TTL-backoff retry.
1897
+ */
1898
+ type TtlBackoffRetryInfrastructure = {
1899
+ /**
1900
+ * The wait queue for holding messages during backoff delay.
1901
+ * This is a classic queue with a dead letter exchange pointing back to the main queue.
1902
+ */
1903
+ waitQueue: QueueDefinition;
1904
+ /**
1905
+ * Binding that routes failed messages to the wait queue.
1906
+ */
1907
+ waitQueueBinding: QueueBindingDefinition;
1908
+ /**
1909
+ * Binding that routes retried messages back to the main queue.
1910
+ */
1911
+ mainQueueRetryBinding: QueueBindingDefinition;
1912
+ };
1913
+ /**
1914
+ * Create TTL-backoff retry infrastructure for a queue.
1915
+ *
1916
+ * This builder helper generates the wait queue and bindings needed for TTL-backoff retry.
1917
+ * The generated infrastructure can be spread into a contract definition.
1918
+ *
1919
+ * TTL-backoff retry works by:
1920
+ * 1. Failed messages are sent to the DLX with routing key `{queueName}-wait`
1921
+ * 2. The wait queue receives these messages and holds them for a TTL period
1922
+ * 3. After TTL expires, messages are dead-lettered back to the DLX with routing key `{queueName}`
1923
+ * 4. The main queue receives the retried message via its binding to the DLX
1924
+ *
1925
+ * @param queue - The main queue definition (must have deadLetter configured)
1926
+ * @param options - Optional configuration for the wait queue
1927
+ * @param options.waitQueueDurable - Whether the wait queue should be durable (default: same as main queue)
1928
+ * @returns TTL-backoff retry infrastructure containing wait queue and bindings
1929
+ * @throws {Error} If the queue does not have a dead letter exchange configured
1930
+ *
1931
+ * @example
1932
+ * ```typescript
1933
+ * const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
1934
+ * const orderQueue = defineQueue('order-processing', {
1935
+ * type: 'quorum',
1936
+ * deadLetter: { exchange: dlx },
1937
+ * retry: {
1938
+ * mode: 'ttl-backoff',
1939
+ * maxRetries: 5,
1940
+ * initialDelayMs: 1000,
1941
+ * },
1942
+ * });
1943
+ *
1944
+ * // Generate TTL-backoff infrastructure
1945
+ * const retryInfra = defineTtlBackoffRetryInfrastructure(orderQueue);
1946
+ *
1947
+ * // Spread into contract
1948
+ * const contract = defineContract({
1949
+ * exchanges: { dlx },
1950
+ * queues: {
1951
+ * orderProcessing: orderQueue,
1952
+ * orderProcessingWait: retryInfra.waitQueue,
1953
+ * },
1954
+ * bindings: {
1955
+ * ...// your other bindings
1956
+ * orderWaitBinding: retryInfra.waitQueueBinding,
1957
+ * orderRetryBinding: retryInfra.mainQueueRetryBinding,
1958
+ * },
1959
+ * // ... publishers and consumers
1960
+ * });
1961
+ * ```
1962
+ */
1963
+ declare function defineTtlBackoffRetryInfrastructure(queueEntry: QueueEntry, options?: {
1964
+ waitQueueDurable?: boolean;
1965
+ }): TtlBackoffRetryInfrastructure;
1478
1966
  //#endregion
1479
- export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type CompressionAlgorithm, type ConsumerDefinition, type ConsumerFirstResult, type ConsumerFirstResultWithRoutingKey, type ContractDefinition, type DeadLetterConfig, type DirectExchangeDefinition, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type InferConsumerNames, type InferPublisherNames, type MatchingRoutingKey, type MessageDefinition, type PublisherDefinition, type PublisherFirstResult, type PublisherFirstResultWithRoutingKey, type QueueBindingDefinition, type QueueDefinition, type RoutingKey, type TopicExchangeDefinition, defineConsumer, defineConsumerFirst, defineContract, defineExchange, defineExchangeBinding, defineMessage, definePublisher, definePublisherFirst, defineQueue, defineQueueBinding };
1967
+ export { type AnySchema, type BaseExchangeDefinition, type BindingDefinition, type BindingPattern, type ClassicQueueDefinition, type ClassicQueueOptions, type CompressionAlgorithm, type ConsumerDefinition, type ConsumerFirstResult, type ConsumerFirstResultWithRoutingKey, type ContractDefinition, type DeadLetterConfig, type DefineQueueOptions, type DirectExchangeDefinition, type ExchangeBindingDefinition, type ExchangeDefinition, type FanoutExchangeDefinition, type InferConsumerNames, type InferPublisherNames, type MatchingRoutingKey, type MessageDefinition, type PublisherDefinition, type PublisherFirstResult, type PublisherFirstResultWithRoutingKey, type QueueBindingDefinition, type QueueDefinition, type QueueEntry, type QueueType, type QueueWithTtlBackoffInfrastructure, type QuorumNativeRetryOptions, type QuorumQueueDefinition, type QuorumQueueOptions, type RoutingKey, type TopicExchangeDefinition, type TtlBackoffRetryInfrastructure, type TtlBackoffRetryOptions, defineConsumer, defineConsumerFirst, defineContract, defineExchange, defineExchangeBinding, defineMessage, definePublisher, definePublisherFirst, defineQueue, defineQueueBinding, defineTtlBackoffRetryInfrastructure, extractQueue };
1480
1968
  //# sourceMappingURL=index.d.mts.map