@amqp-contract/contract 0.11.0 → 0.13.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/README.md +28 -14
- package/dist/index.cjs +550 -238
- package/dist/index.d.cts +787 -405
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +787 -405
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +540 -236
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +738 -216
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
//#region src/builder.ts
|
|
2
|
+
//#region src/builder/exchange.ts
|
|
3
3
|
/**
|
|
4
4
|
* Define an AMQP exchange.
|
|
5
5
|
*
|
|
@@ -20,6 +20,263 @@ function defineExchange(name, type, options) {
|
|
|
20
20
|
...options
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/builder/message.ts
|
|
26
|
+
/**
|
|
27
|
+
* Define a message definition with payload and optional headers/metadata.
|
|
28
|
+
*
|
|
29
|
+
* A message definition specifies the schema for message payloads and headers using
|
|
30
|
+
* Standard Schema v1 compatible libraries (Zod, Valibot, ArkType, etc.).
|
|
31
|
+
* The schemas are used for automatic validation when publishing or consuming messages.
|
|
32
|
+
*
|
|
33
|
+
* @param payload - The payload schema (must be Standard Schema v1 compatible)
|
|
34
|
+
* @param options - Optional message metadata
|
|
35
|
+
* @param options.headers - Optional header schema for message headers
|
|
36
|
+
* @param options.summary - Brief description for documentation (used in AsyncAPI generation)
|
|
37
|
+
* @param options.description - Detailed description for documentation (used in AsyncAPI generation)
|
|
38
|
+
* @returns A message definition with inferred types
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* import { z } from 'zod';
|
|
43
|
+
*
|
|
44
|
+
* const orderMessage = defineMessage(
|
|
45
|
+
* z.object({
|
|
46
|
+
* orderId: z.string().uuid(),
|
|
47
|
+
* customerId: z.string().uuid(),
|
|
48
|
+
* amount: z.number().positive(),
|
|
49
|
+
* items: z.array(z.object({
|
|
50
|
+
* productId: z.string(),
|
|
51
|
+
* quantity: z.number().int().positive(),
|
|
52
|
+
* })),
|
|
53
|
+
* }),
|
|
54
|
+
* {
|
|
55
|
+
* summary: 'Order created event',
|
|
56
|
+
* description: 'Emitted when a new order is created in the system'
|
|
57
|
+
* }
|
|
58
|
+
* );
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
function defineMessage(payload, options) {
|
|
62
|
+
return {
|
|
63
|
+
payload,
|
|
64
|
+
...options
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/builder/binding.ts
|
|
70
|
+
/**
|
|
71
|
+
* Type guard to check if a queue entry is a QueueWithTtlBackoffInfrastructure.
|
|
72
|
+
* Duplicated here to avoid circular dependency with queue.ts.
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
function isQueueWithTtlBackoffInfrastructure$1(entry) {
|
|
76
|
+
return typeof entry === "object" && entry !== null && "__brand" in entry && entry.__brand === "QueueWithTtlBackoffInfrastructure";
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Extract the plain QueueDefinition from a QueueEntry.
|
|
80
|
+
* Duplicated here to avoid circular dependency with queue.ts.
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
function extractQueueInternal(entry) {
|
|
84
|
+
if (isQueueWithTtlBackoffInfrastructure$1(entry)) return entry.queue;
|
|
85
|
+
return entry;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Define a binding between a queue and an exchange.
|
|
89
|
+
*
|
|
90
|
+
* This is the implementation function - use the type-specific overloads for better type safety.
|
|
91
|
+
*
|
|
92
|
+
* @param queue - The queue definition or queue with infrastructure to bind
|
|
93
|
+
* @param exchange - The exchange definition
|
|
94
|
+
* @param options - Optional binding configuration
|
|
95
|
+
* @returns A queue binding definition
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
98
|
+
function defineQueueBinding(queue, exchange, options) {
|
|
99
|
+
const queueDef = extractQueueInternal(queue);
|
|
100
|
+
if (exchange.type === "fanout") return {
|
|
101
|
+
type: "queue",
|
|
102
|
+
queue: queueDef,
|
|
103
|
+
exchange,
|
|
104
|
+
...options?.arguments && { arguments: options.arguments }
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
type: "queue",
|
|
108
|
+
queue: queueDef,
|
|
109
|
+
exchange,
|
|
110
|
+
routingKey: options?.routingKey,
|
|
111
|
+
...options?.arguments && { arguments: options.arguments }
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Internal helper to call defineQueueBinding with proper type handling.
|
|
116
|
+
* Used by queue.ts to avoid circular dependency.
|
|
117
|
+
* @internal
|
|
118
|
+
*/
|
|
119
|
+
function defineQueueBindingInternal(queue, exchange, options) {
|
|
120
|
+
if (exchange.type === "fanout") return defineQueueBinding(queue, exchange, options);
|
|
121
|
+
return defineQueueBinding(queue, exchange, options);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Define a binding between two exchanges (exchange-to-exchange routing).
|
|
125
|
+
*
|
|
126
|
+
* This is the implementation function - use the type-specific overloads for better type safety.
|
|
127
|
+
*
|
|
128
|
+
* @param destination - The destination exchange definition
|
|
129
|
+
* @param source - The source exchange definition
|
|
130
|
+
* @param options - Optional binding configuration
|
|
131
|
+
* @returns An exchange binding definition
|
|
132
|
+
* @internal
|
|
133
|
+
*/
|
|
134
|
+
function defineExchangeBinding(destination, source, options) {
|
|
135
|
+
if (source.type === "fanout") return {
|
|
136
|
+
type: "exchange",
|
|
137
|
+
source,
|
|
138
|
+
destination,
|
|
139
|
+
...options?.arguments && { arguments: options.arguments }
|
|
140
|
+
};
|
|
141
|
+
return {
|
|
142
|
+
type: "exchange",
|
|
143
|
+
source,
|
|
144
|
+
destination,
|
|
145
|
+
routingKey: options?.routingKey ?? "",
|
|
146
|
+
...options?.arguments && { arguments: options.arguments }
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/builder/queue.ts
|
|
152
|
+
/**
|
|
153
|
+
* Resolve TTL-backoff retry options with defaults applied.
|
|
154
|
+
* @internal
|
|
155
|
+
*/
|
|
156
|
+
function resolveTtlBackoffOptions(options) {
|
|
157
|
+
return {
|
|
158
|
+
mode: "ttl-backoff",
|
|
159
|
+
maxRetries: options?.maxRetries ?? 3,
|
|
160
|
+
initialDelayMs: options?.initialDelayMs ?? 1e3,
|
|
161
|
+
maxDelayMs: options?.maxDelayMs ?? 3e4,
|
|
162
|
+
backoffMultiplier: options?.backoffMultiplier ?? 2,
|
|
163
|
+
jitter: options?.jitter ?? true
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Type guard to check if a queue entry is a QueueWithTtlBackoffInfrastructure.
|
|
168
|
+
*
|
|
169
|
+
* When you configure a queue with TTL-backoff retry and a dead letter exchange,
|
|
170
|
+
* `defineQueue` returns a `QueueWithTtlBackoffInfrastructure` instead of a plain
|
|
171
|
+
* `QueueDefinition`. This type guard helps you distinguish between the two.
|
|
172
|
+
*
|
|
173
|
+
* **When to use:**
|
|
174
|
+
* - When you need to check the type of a queue entry at runtime
|
|
175
|
+
* - When writing generic code that handles both plain queues and infrastructure wrappers
|
|
176
|
+
*
|
|
177
|
+
* **Related functions:**
|
|
178
|
+
* - `extractQueue()` - Use this to get the underlying queue definition from either type
|
|
179
|
+
*
|
|
180
|
+
* @param entry - The queue entry to check
|
|
181
|
+
* @returns True if the entry is a QueueWithTtlBackoffInfrastructure, false otherwise
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* const queue = defineQueue('orders', {
|
|
186
|
+
* deadLetter: { exchange: dlx },
|
|
187
|
+
* retry: { mode: 'ttl-backoff' },
|
|
188
|
+
* });
|
|
189
|
+
*
|
|
190
|
+
* if (isQueueWithTtlBackoffInfrastructure(queue)) {
|
|
191
|
+
* // queue has .queue, .waitQueue, .waitQueueBinding, .mainQueueRetryBinding
|
|
192
|
+
* console.log('Wait queue:', queue.waitQueue.name);
|
|
193
|
+
* } else {
|
|
194
|
+
* // queue is a plain QueueDefinition
|
|
195
|
+
* console.log('Queue:', queue.name);
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
function isQueueWithTtlBackoffInfrastructure(entry) {
|
|
200
|
+
return typeof entry === "object" && entry !== null && "__brand" in entry && entry.__brand === "QueueWithTtlBackoffInfrastructure";
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Extract the plain QueueDefinition from a QueueEntry.
|
|
204
|
+
*
|
|
205
|
+
* **Why this function exists:**
|
|
206
|
+
* When you configure a queue with TTL-backoff retry and a dead letter exchange,
|
|
207
|
+
* `defineQueue` (or `defineTtlBackoffQueue`) returns a wrapper object that includes
|
|
208
|
+
* the main queue, wait queue, and bindings. This function extracts the underlying
|
|
209
|
+
* queue definition so you can access properties like `name`, `type`, etc.
|
|
210
|
+
*
|
|
211
|
+
* **When to use:**
|
|
212
|
+
* - When you need to access queue properties (name, type, deadLetter, etc.)
|
|
213
|
+
* - When passing a queue to functions that expect a plain QueueDefinition
|
|
214
|
+
* - Works safely on both plain queues and infrastructure wrappers
|
|
215
|
+
*
|
|
216
|
+
* **How it works:**
|
|
217
|
+
* - If the entry is a `QueueWithTtlBackoffInfrastructure`, returns `entry.queue`
|
|
218
|
+
* - Otherwise, returns the entry as-is (it's already a plain QueueDefinition)
|
|
219
|
+
*
|
|
220
|
+
* @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
|
|
221
|
+
* @returns The plain QueueDefinition
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* import { defineQueue, defineTtlBackoffQueue, extractQueue } from '@amqp-contract/contract';
|
|
226
|
+
*
|
|
227
|
+
* // TTL-backoff queue returns a wrapper
|
|
228
|
+
* const orderQueue = defineTtlBackoffQueue('orders', {
|
|
229
|
+
* deadLetterExchange: dlx,
|
|
230
|
+
* maxRetries: 3,
|
|
231
|
+
* });
|
|
232
|
+
*
|
|
233
|
+
* // Use extractQueue to access the queue name
|
|
234
|
+
* const queueName = extractQueue(orderQueue).name; // 'orders'
|
|
235
|
+
*
|
|
236
|
+
* // Also works safely on plain queues
|
|
237
|
+
* const plainQueue = defineQueue('simple', { type: 'quorum', retry: { mode: 'quorum-native' } });
|
|
238
|
+
* const plainName = extractQueue(plainQueue).name; // 'simple'
|
|
239
|
+
*
|
|
240
|
+
* // Access other properties
|
|
241
|
+
* const queueDef = extractQueue(orderQueue);
|
|
242
|
+
* console.log(queueDef.name); // 'orders'
|
|
243
|
+
* console.log(queueDef.type); // 'quorum'
|
|
244
|
+
* console.log(queueDef.deadLetter); // { exchange: dlx, ... }
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
* @see isQueueWithTtlBackoffInfrastructure - Type guard to check if extraction is needed
|
|
248
|
+
* @see defineTtlBackoffQueue - Creates queues with TTL-backoff infrastructure
|
|
249
|
+
*/
|
|
250
|
+
function extractQueue(entry) {
|
|
251
|
+
if (isQueueWithTtlBackoffInfrastructure(entry)) return entry.queue;
|
|
252
|
+
return entry;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Wrap a queue definition with TTL-backoff retry infrastructure.
|
|
256
|
+
* @internal
|
|
257
|
+
*/
|
|
258
|
+
function wrapWithTtlBackoffInfrastructure(queue) {
|
|
259
|
+
if (!queue.deadLetter) throw new Error(`Queue "${queue.name}" does not have a dead letter exchange configured. TTL-backoff retry requires deadLetter to be set on the queue.`);
|
|
260
|
+
const dlx = queue.deadLetter.exchange;
|
|
261
|
+
const waitQueueName = `${queue.name}-wait`;
|
|
262
|
+
const waitQueue = {
|
|
263
|
+
name: waitQueueName,
|
|
264
|
+
type: "quorum",
|
|
265
|
+
durable: queue.durable ?? true,
|
|
266
|
+
deadLetter: {
|
|
267
|
+
exchange: dlx,
|
|
268
|
+
routingKey: queue.name
|
|
269
|
+
},
|
|
270
|
+
retry: resolveTtlBackoffOptions(void 0)
|
|
271
|
+
};
|
|
272
|
+
return {
|
|
273
|
+
__brand: "QueueWithTtlBackoffInfrastructure",
|
|
274
|
+
queue,
|
|
275
|
+
waitQueue,
|
|
276
|
+
waitQueueBinding: defineQueueBindingInternal(waitQueue, dlx, { routingKey: waitQueueName }),
|
|
277
|
+
mainQueueRetryBinding: defineQueueBindingInternal(queue, dlx, { routingKey: queue.name })
|
|
278
|
+
};
|
|
279
|
+
}
|
|
23
280
|
/**
|
|
24
281
|
* Define an AMQP queue.
|
|
25
282
|
*
|
|
@@ -92,22 +349,30 @@ function defineQueue(name, options) {
|
|
|
92
349
|
if (opts.arguments !== void 0) baseProps.arguments = opts.arguments;
|
|
93
350
|
if (type === "quorum") {
|
|
94
351
|
const quorumOpts = opts;
|
|
352
|
+
const inputRetry = quorumOpts.retry ?? { mode: "ttl-backoff" };
|
|
353
|
+
if (inputRetry.mode === "quorum-native") {
|
|
354
|
+
if (quorumOpts.deliveryLimit === void 0) throw new Error(`Queue "${name}" uses quorum-native retry mode but deliveryLimit is not configured. Quorum-native retry requires deliveryLimit to be set.`);
|
|
355
|
+
}
|
|
356
|
+
const retry$1 = inputRetry.mode === "quorum-native" ? inputRetry : resolveTtlBackoffOptions(inputRetry);
|
|
95
357
|
const queueDefinition$1 = {
|
|
96
358
|
...baseProps,
|
|
97
|
-
type: "quorum"
|
|
359
|
+
type: "quorum",
|
|
360
|
+
retry: retry$1
|
|
98
361
|
};
|
|
99
362
|
if (quorumOpts.deliveryLimit !== void 0) {
|
|
100
363
|
if (quorumOpts.deliveryLimit < 1 || !Number.isInteger(quorumOpts.deliveryLimit)) throw new Error(`Invalid deliveryLimit: ${quorumOpts.deliveryLimit}. Must be a positive integer.`);
|
|
101
364
|
queueDefinition$1.deliveryLimit = quorumOpts.deliveryLimit;
|
|
102
365
|
}
|
|
103
|
-
if (
|
|
104
|
-
if (quorumOpts.retry?.mode === "ttl-backoff" && queueDefinition$1.deadLetter) return wrapWithTtlBackoffInfrastructure(queueDefinition$1);
|
|
366
|
+
if (retry$1.mode === "ttl-backoff" && queueDefinition$1.deadLetter) return wrapWithTtlBackoffInfrastructure(queueDefinition$1);
|
|
105
367
|
return queueDefinition$1;
|
|
106
368
|
}
|
|
107
369
|
const classicOpts = opts;
|
|
370
|
+
if (classicOpts.retry?.mode === "quorum-native") throw new Error(`Queue "${name}" uses quorum-native retry mode but is a classic queue. Quorum-native retry requires quorum queues (type: "quorum").`);
|
|
371
|
+
const retry = resolveTtlBackoffOptions(classicOpts.retry);
|
|
108
372
|
const queueDefinition = {
|
|
109
373
|
...baseProps,
|
|
110
|
-
type: "classic"
|
|
374
|
+
type: "classic",
|
|
375
|
+
retry
|
|
111
376
|
};
|
|
112
377
|
if (classicOpts.exclusive !== void 0) queueDefinition.exclusive = classicOpts.exclusive;
|
|
113
378
|
if (classicOpts.maxPriority !== void 0) {
|
|
@@ -117,129 +382,132 @@ function defineQueue(name, options) {
|
|
|
117
382
|
"x-max-priority": classicOpts.maxPriority
|
|
118
383
|
};
|
|
119
384
|
}
|
|
120
|
-
if (
|
|
121
|
-
if (classicOpts.retry?.mode === "ttl-backoff" && queueDefinition.deadLetter) return wrapWithTtlBackoffInfrastructure(queueDefinition);
|
|
385
|
+
if (retry.mode === "ttl-backoff" && queueDefinition.deadLetter) return wrapWithTtlBackoffInfrastructure(queueDefinition);
|
|
122
386
|
return queueDefinition;
|
|
123
387
|
}
|
|
124
388
|
/**
|
|
125
|
-
*
|
|
126
|
-
* @internal
|
|
127
|
-
*/
|
|
128
|
-
function wrapWithTtlBackoffInfrastructure(queue) {
|
|
129
|
-
if (!queue.deadLetter) throw new Error(`Queue "${queue.name}" does not have a dead letter exchange configured. TTL-backoff retry requires deadLetter to be set on the queue.`);
|
|
130
|
-
const dlx = queue.deadLetter.exchange;
|
|
131
|
-
const waitQueueName = `${queue.name}-wait`;
|
|
132
|
-
const waitQueue = {
|
|
133
|
-
name: waitQueueName,
|
|
134
|
-
type: "quorum",
|
|
135
|
-
durable: queue.durable ?? true,
|
|
136
|
-
deadLetter: {
|
|
137
|
-
exchange: dlx,
|
|
138
|
-
routingKey: queue.name
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
return {
|
|
142
|
-
__brand: "QueueWithTtlBackoffInfrastructure",
|
|
143
|
-
queue,
|
|
144
|
-
waitQueue,
|
|
145
|
-
waitQueueBinding: callDefineQueueBinding(waitQueue, dlx, { routingKey: waitQueueName }),
|
|
146
|
-
mainQueueRetryBinding: callDefineQueueBinding(queue, dlx, { routingKey: queue.name })
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Define a message definition with payload and optional headers/metadata.
|
|
389
|
+
* Create a quorum queue with quorum-native retry.
|
|
151
390
|
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
391
|
+
* This is a simplified helper that enforces best practices:
|
|
392
|
+
* - Uses quorum queues (recommended for most use cases)
|
|
393
|
+
* - Requires dead letter exchange for failed message handling
|
|
394
|
+
* - Uses quorum-native retry mode (simpler than TTL-backoff)
|
|
155
395
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* @
|
|
396
|
+
* **When to use:**
|
|
397
|
+
* - You want simple, immediate retries without exponential backoff
|
|
398
|
+
* - You don't need configurable delays between retries
|
|
399
|
+
* - You want the simplest retry configuration
|
|
400
|
+
*
|
|
401
|
+
* @param name - The queue name
|
|
402
|
+
* @param options - Configuration options
|
|
403
|
+
* @returns A quorum queue definition with quorum-native retry
|
|
162
404
|
*
|
|
163
405
|
* @example
|
|
164
406
|
* ```typescript
|
|
165
|
-
*
|
|
407
|
+
* const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
|
|
166
408
|
*
|
|
167
|
-
* const
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* {
|
|
178
|
-
* summary: 'Order created event',
|
|
179
|
-
* description: 'Emitted when a new order is created in the system'
|
|
180
|
-
* }
|
|
181
|
-
* );
|
|
409
|
+
* const orderQueue = defineQuorumQueue('order-processing', {
|
|
410
|
+
* deadLetterExchange: dlx,
|
|
411
|
+
* deliveryLimit: 3, // Retry up to 3 times
|
|
412
|
+
* });
|
|
413
|
+
*
|
|
414
|
+
* const contract = defineContract({
|
|
415
|
+
* exchanges: { dlx },
|
|
416
|
+
* queues: { orderProcessing: orderQueue },
|
|
417
|
+
* // ...
|
|
418
|
+
* });
|
|
182
419
|
* ```
|
|
420
|
+
*
|
|
421
|
+
* @see defineQueue - For full queue configuration options
|
|
422
|
+
* @see defineTtlBackoffQueue - For queues with exponential backoff retry
|
|
183
423
|
*/
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
424
|
+
function defineQuorumQueue(name, options) {
|
|
425
|
+
const { deadLetterExchange, deadLetterRoutingKey, deliveryLimit, autoDelete, arguments: args } = options;
|
|
426
|
+
const queueOptions = {
|
|
427
|
+
type: "quorum",
|
|
428
|
+
deadLetter: deadLetterRoutingKey ? {
|
|
429
|
+
exchange: deadLetterExchange,
|
|
430
|
+
routingKey: deadLetterRoutingKey
|
|
431
|
+
} : { exchange: deadLetterExchange },
|
|
432
|
+
deliveryLimit,
|
|
433
|
+
retry: { mode: "quorum-native" }
|
|
188
434
|
};
|
|
435
|
+
if (autoDelete !== void 0) queueOptions.autoDelete = autoDelete;
|
|
436
|
+
if (args !== void 0) queueOptions.arguments = args;
|
|
437
|
+
return defineQueue(name, queueOptions);
|
|
189
438
|
}
|
|
190
439
|
/**
|
|
191
|
-
*
|
|
440
|
+
* Create a queue with TTL-backoff retry (exponential backoff).
|
|
192
441
|
*
|
|
193
|
-
* This is
|
|
442
|
+
* This is a simplified helper that enforces best practices:
|
|
443
|
+
* - Uses quorum queues (recommended for most use cases)
|
|
444
|
+
* - Requires dead letter exchange for retry routing
|
|
445
|
+
* - Uses TTL-backoff retry mode with configurable delays
|
|
446
|
+
* - Automatically generates wait queue and bindings
|
|
194
447
|
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* @internal
|
|
200
|
-
*/
|
|
201
|
-
function defineQueueBinding(queue, exchange, options) {
|
|
202
|
-
const queueDef = extractQueue(queue);
|
|
203
|
-
if (exchange.type === "fanout") return {
|
|
204
|
-
type: "queue",
|
|
205
|
-
queue: queueDef,
|
|
206
|
-
exchange,
|
|
207
|
-
...options?.arguments && { arguments: options.arguments }
|
|
208
|
-
};
|
|
209
|
-
return {
|
|
210
|
-
type: "queue",
|
|
211
|
-
queue: queueDef,
|
|
212
|
-
exchange,
|
|
213
|
-
routingKey: options?.routingKey,
|
|
214
|
-
...options?.arguments && { arguments: options.arguments }
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Define a binding between two exchanges (exchange-to-exchange routing).
|
|
448
|
+
* **When to use:**
|
|
449
|
+
* - You need exponential backoff between retries
|
|
450
|
+
* - You want configurable delays (initial delay, max delay, jitter)
|
|
451
|
+
* - You're processing messages that may need time before retry
|
|
219
452
|
*
|
|
220
|
-
*
|
|
453
|
+
* **Returns:** A `QueueWithTtlBackoffInfrastructure` object that includes the
|
|
454
|
+
* main queue, wait queue, and bindings. Pass this directly to `defineContract`
|
|
455
|
+
* and it will be expanded automatically.
|
|
221
456
|
*
|
|
222
|
-
* @param
|
|
223
|
-
* @param
|
|
224
|
-
* @
|
|
225
|
-
*
|
|
226
|
-
* @
|
|
457
|
+
* @param name - The queue name
|
|
458
|
+
* @param options - Configuration options
|
|
459
|
+
* @returns A queue with TTL-backoff infrastructure
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* ```typescript
|
|
463
|
+
* const dlx = defineExchange('orders-dlx', 'direct', { durable: true });
|
|
464
|
+
*
|
|
465
|
+
* const orderQueue = defineTtlBackoffQueue('order-processing', {
|
|
466
|
+
* deadLetterExchange: dlx,
|
|
467
|
+
* maxRetries: 5,
|
|
468
|
+
* initialDelayMs: 1000, // Start with 1s delay
|
|
469
|
+
* maxDelayMs: 30000, // Cap at 30s
|
|
470
|
+
* });
|
|
471
|
+
*
|
|
472
|
+
* const contract = defineContract({
|
|
473
|
+
* exchanges: { dlx },
|
|
474
|
+
* queues: { orderProcessing: orderQueue }, // Wait queue auto-added
|
|
475
|
+
* // ... bindings auto-generated
|
|
476
|
+
* });
|
|
477
|
+
*
|
|
478
|
+
* // To access the underlying queue definition (e.g., for the queue name):
|
|
479
|
+
* import { extractQueue } from '@amqp-contract/contract';
|
|
480
|
+
* const queueName = extractQueue(orderQueue).name;
|
|
481
|
+
* ```
|
|
482
|
+
*
|
|
483
|
+
* @see defineQueue - For full queue configuration options
|
|
484
|
+
* @see defineQuorumQueue - For queues with quorum-native retry (simpler, immediate retries)
|
|
485
|
+
* @see extractQueue - To access the underlying queue definition
|
|
227
486
|
*/
|
|
228
|
-
function
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
487
|
+
function defineTtlBackoffQueue(name, options) {
|
|
488
|
+
const { deadLetterExchange, deadLetterRoutingKey, maxRetries, initialDelayMs, maxDelayMs, backoffMultiplier, jitter, autoDelete, arguments: args } = options;
|
|
489
|
+
const deadLetter = deadLetterRoutingKey ? {
|
|
490
|
+
exchange: deadLetterExchange,
|
|
491
|
+
routingKey: deadLetterRoutingKey
|
|
492
|
+
} : { exchange: deadLetterExchange };
|
|
493
|
+
const retryOptions = { mode: "ttl-backoff" };
|
|
494
|
+
if (maxRetries !== void 0) retryOptions.maxRetries = maxRetries;
|
|
495
|
+
if (initialDelayMs !== void 0) retryOptions.initialDelayMs = initialDelayMs;
|
|
496
|
+
if (maxDelayMs !== void 0) retryOptions.maxDelayMs = maxDelayMs;
|
|
497
|
+
if (backoffMultiplier !== void 0) retryOptions.backoffMultiplier = backoffMultiplier;
|
|
498
|
+
if (jitter !== void 0) retryOptions.jitter = jitter;
|
|
499
|
+
const queueOptions = {
|
|
500
|
+
type: "quorum",
|
|
501
|
+
deadLetter,
|
|
502
|
+
retry: retryOptions
|
|
241
503
|
};
|
|
504
|
+
if (autoDelete !== void 0) queueOptions.autoDelete = autoDelete;
|
|
505
|
+
if (args !== void 0) queueOptions.arguments = args;
|
|
506
|
+
return defineQueue(name, queueOptions);
|
|
242
507
|
}
|
|
508
|
+
|
|
509
|
+
//#endregion
|
|
510
|
+
//#region src/builder/publisher.ts
|
|
243
511
|
/**
|
|
244
512
|
* Define a message publisher.
|
|
245
513
|
*
|
|
@@ -263,6 +531,18 @@ function definePublisher(exchange, message, options) {
|
|
|
263
531
|
};
|
|
264
532
|
}
|
|
265
533
|
/**
|
|
534
|
+
* Helper to call definePublisher with proper type handling.
|
|
535
|
+
* Type safety is enforced by overloaded public function signatures.
|
|
536
|
+
* @internal
|
|
537
|
+
*/
|
|
538
|
+
function definePublisherInternal(exchange, message, options) {
|
|
539
|
+
if (exchange.type === "fanout") return definePublisher(exchange, message, options);
|
|
540
|
+
return definePublisher(exchange, message, options);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
//#endregion
|
|
544
|
+
//#region src/builder/consumer.ts
|
|
545
|
+
/**
|
|
266
546
|
* Define a message consumer.
|
|
267
547
|
*
|
|
268
548
|
* A consumer receives and processes messages from a queue. The message schema is validated
|
|
@@ -271,6 +551,19 @@ function definePublisher(exchange, message, options) {
|
|
|
271
551
|
* Consumers are associated with a specific queue and message type. When you create a worker
|
|
272
552
|
* with this consumer, it will process messages from the queue according to the schema.
|
|
273
553
|
*
|
|
554
|
+
* **Which pattern to use:**
|
|
555
|
+
*
|
|
556
|
+
* | Pattern | Best for | Description |
|
|
557
|
+
* |---------|----------|-------------|
|
|
558
|
+
* | `definePublisher` + `defineConsumer` | Independent definition | Define publishers and consumers separately with manual schema consistency |
|
|
559
|
+
* | `defineEventPublisher` + `defineEventConsumer` | Event broadcasting | Define event publisher first, create consumers that subscribe to it |
|
|
560
|
+
* | `defineCommandConsumer` + `defineCommandPublisher` | Task queues | Define command consumer first, create publishers that send commands to it |
|
|
561
|
+
*
|
|
562
|
+
* Use `defineCommandConsumer` when:
|
|
563
|
+
* - One consumer receives from multiple publishers
|
|
564
|
+
* - You want automatic schema consistency between consumer and publishers
|
|
565
|
+
* - You're building task queue or command patterns
|
|
566
|
+
*
|
|
274
567
|
* @param queue - The queue definition to consume from
|
|
275
568
|
* @param message - The message definition with payload schema
|
|
276
569
|
* @param options - Optional consumer configuration
|
|
@@ -303,6 +596,9 @@ function definePublisher(exchange, message, options) {
|
|
|
303
596
|
* // connection
|
|
304
597
|
* // });
|
|
305
598
|
* ```
|
|
599
|
+
*
|
|
600
|
+
* @see defineCommandConsumer - For task queue patterns with automatic schema consistency
|
|
601
|
+
* @see defineEventPublisher - For event-driven patterns with automatic schema consistency
|
|
306
602
|
*/
|
|
307
603
|
function defineConsumer(queue, message, options) {
|
|
308
604
|
return {
|
|
@@ -311,6 +607,99 @@ function defineConsumer(queue, message, options) {
|
|
|
311
607
|
...options
|
|
312
608
|
};
|
|
313
609
|
}
|
|
610
|
+
|
|
611
|
+
//#endregion
|
|
612
|
+
//#region src/builder/event.ts
|
|
613
|
+
/**
|
|
614
|
+
* Implementation of defineEventPublisher.
|
|
615
|
+
* @internal
|
|
616
|
+
*/
|
|
617
|
+
function defineEventPublisher(exchange, message, options) {
|
|
618
|
+
const config = {
|
|
619
|
+
__brand: "EventPublisherConfig",
|
|
620
|
+
exchange,
|
|
621
|
+
message,
|
|
622
|
+
routingKey: options?.routingKey
|
|
623
|
+
};
|
|
624
|
+
if (options?.arguments !== void 0) config.arguments = options.arguments;
|
|
625
|
+
return config;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Implementation of defineEventConsumer.
|
|
629
|
+
* @internal
|
|
630
|
+
*/
|
|
631
|
+
function defineEventConsumer(eventPublisher, queue, options) {
|
|
632
|
+
const { exchange, message, routingKey: publisherRoutingKey } = eventPublisher;
|
|
633
|
+
const bindingRoutingKey = options?.routingKey ?? publisherRoutingKey;
|
|
634
|
+
const bindingOptions = {};
|
|
635
|
+
if (bindingRoutingKey !== void 0) bindingOptions.routingKey = bindingRoutingKey;
|
|
636
|
+
const bindingArguments = options?.arguments ?? eventPublisher.arguments;
|
|
637
|
+
if (bindingArguments !== void 0) bindingOptions.arguments = bindingArguments;
|
|
638
|
+
const binding = defineQueueBindingInternal(queue, exchange, bindingOptions);
|
|
639
|
+
return {
|
|
640
|
+
__brand: "EventConsumerResult",
|
|
641
|
+
consumer: defineConsumer(queue, message),
|
|
642
|
+
binding
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Type guard to check if a value is an EventPublisherConfig.
|
|
647
|
+
*
|
|
648
|
+
* @param value - The value to check
|
|
649
|
+
* @returns True if the value is an EventPublisherConfig
|
|
650
|
+
*/
|
|
651
|
+
function isEventPublisherConfig(value) {
|
|
652
|
+
return typeof value === "object" && value !== null && "__brand" in value && value.__brand === "EventPublisherConfig";
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Type guard to check if a value is an EventConsumerResult.
|
|
656
|
+
*
|
|
657
|
+
* @param value - The value to check
|
|
658
|
+
* @returns True if the value is an EventConsumerResult
|
|
659
|
+
*/
|
|
660
|
+
function isEventConsumerResult(value) {
|
|
661
|
+
return typeof value === "object" && value !== null && "__brand" in value && value.__brand === "EventConsumerResult";
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
//#endregion
|
|
665
|
+
//#region src/builder/command.ts
|
|
666
|
+
/**
|
|
667
|
+
* Implementation of defineCommandConsumer.
|
|
668
|
+
* @internal
|
|
669
|
+
*/
|
|
670
|
+
function defineCommandConsumer(queue, exchange, message, options) {
|
|
671
|
+
return {
|
|
672
|
+
__brand: "CommandConsumerConfig",
|
|
673
|
+
consumer: defineConsumer(queue, message),
|
|
674
|
+
binding: defineQueueBindingInternal(queue, exchange, options),
|
|
675
|
+
exchange,
|
|
676
|
+
message,
|
|
677
|
+
routingKey: options?.routingKey
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Implementation of defineCommandPublisher.
|
|
682
|
+
* @internal
|
|
683
|
+
*/
|
|
684
|
+
function defineCommandPublisher(commandConsumer, options) {
|
|
685
|
+
const { exchange, message, routingKey: consumerRoutingKey } = commandConsumer;
|
|
686
|
+
const publisherRoutingKey = options?.routingKey ?? consumerRoutingKey;
|
|
687
|
+
const publisherOptions = {};
|
|
688
|
+
if (publisherRoutingKey !== void 0) publisherOptions.routingKey = publisherRoutingKey;
|
|
689
|
+
return definePublisherInternal(exchange, message, publisherOptions);
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Type guard to check if a value is a CommandConsumerConfig.
|
|
693
|
+
*
|
|
694
|
+
* @param value - The value to check
|
|
695
|
+
* @returns True if the value is a CommandConsumerConfig
|
|
696
|
+
*/
|
|
697
|
+
function isCommandConsumerConfig(value) {
|
|
698
|
+
return typeof value === "object" && value !== null && "__brand" in value && value.__brand === "CommandConsumerConfig";
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/builder/contract.ts
|
|
314
703
|
/**
|
|
315
704
|
* Define an AMQP contract.
|
|
316
705
|
*
|
|
@@ -381,138 +770,53 @@ function defineConsumer(queue, message, options) {
|
|
|
381
770
|
* ```
|
|
382
771
|
*/
|
|
383
772
|
function defineContract(definition) {
|
|
384
|
-
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
...
|
|
398
|
-
|
|
399
|
-
return {
|
|
400
|
-
...definition,
|
|
401
|
-
queues: expandedQueues,
|
|
402
|
-
bindings: mergedBindings
|
|
773
|
+
const { publishers: inputPublishers, consumers: inputConsumers, ...rest } = definition;
|
|
774
|
+
const result = rest;
|
|
775
|
+
if (definition.queues && Object.keys(definition.queues).length > 0) {
|
|
776
|
+
const expandedQueues = {};
|
|
777
|
+
const queueBindings = {};
|
|
778
|
+
for (const [name, entry] of Object.entries(definition.queues)) if (isQueueWithTtlBackoffInfrastructure(entry)) {
|
|
779
|
+
expandedQueues[name] = entry.queue;
|
|
780
|
+
expandedQueues[`${name}Wait`] = entry.waitQueue;
|
|
781
|
+
queueBindings[`${name}WaitBinding`] = entry.waitQueueBinding;
|
|
782
|
+
queueBindings[`${name}RetryBinding`] = entry.mainQueueRetryBinding;
|
|
783
|
+
} else expandedQueues[name] = entry;
|
|
784
|
+
result.queues = expandedQueues;
|
|
785
|
+
if (Object.keys(queueBindings).length > 0) result.bindings = {
|
|
786
|
+
...result.bindings,
|
|
787
|
+
...queueBindings
|
|
403
788
|
};
|
|
404
789
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
*/
|
|
414
|
-
function isQueueWithTtlBackoffInfrastructure(entry) {
|
|
415
|
-
return typeof entry === "object" && entry !== null && "__brand" in entry && entry.__brand === "QueueWithTtlBackoffInfrastructure";
|
|
416
|
-
}
|
|
417
|
-
/**
|
|
418
|
-
* Extract the plain QueueDefinition from a QueueEntry.
|
|
419
|
-
* If the entry is a QueueWithTtlBackoffInfrastructure, returns the inner queue.
|
|
420
|
-
* Otherwise, returns the entry as-is.
|
|
421
|
-
*
|
|
422
|
-
* @param entry - The queue entry (either plain QueueDefinition or QueueWithTtlBackoffInfrastructure)
|
|
423
|
-
* @returns The plain QueueDefinition
|
|
424
|
-
*
|
|
425
|
-
* @example
|
|
426
|
-
* ```typescript
|
|
427
|
-
* const queue = defineQueue('orders', { retry: { mode: 'ttl-backoff' }, deadLetter: { exchange: dlx } });
|
|
428
|
-
* const plainQueue = extractQueue(queue); // Returns the inner QueueDefinition
|
|
429
|
-
* ```
|
|
430
|
-
*/
|
|
431
|
-
function extractQueue(entry) {
|
|
432
|
-
if (isQueueWithTtlBackoffInfrastructure(entry)) return entry.queue;
|
|
433
|
-
return entry;
|
|
434
|
-
}
|
|
435
|
-
/**
|
|
436
|
-
* Helper to call definePublisher with proper type handling.
|
|
437
|
-
* Type safety is enforced by overloaded public function signatures.
|
|
438
|
-
* @internal
|
|
439
|
-
*/
|
|
440
|
-
function callDefinePublisher(exchange, message, options) {
|
|
441
|
-
if (exchange.type === "fanout") return definePublisher(exchange, message, options);
|
|
442
|
-
return definePublisher(exchange, message, options);
|
|
443
|
-
}
|
|
444
|
-
/**
|
|
445
|
-
* Helper to call defineQueueBinding with proper type handling.
|
|
446
|
-
* Type safety is enforced by overloaded public function signatures.
|
|
447
|
-
* @internal
|
|
448
|
-
*/
|
|
449
|
-
function callDefineQueueBinding(queue, exchange, options) {
|
|
450
|
-
if (exchange.type === "fanout") return defineQueueBinding(queue, exchange, options);
|
|
451
|
-
return defineQueueBinding(queue, exchange, options);
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* Implementation of definePublisherFirst.
|
|
455
|
-
* @internal
|
|
456
|
-
*/
|
|
457
|
-
function definePublisherFirst(exchange, message, options) {
|
|
458
|
-
const publisher = callDefinePublisher(exchange, message, options);
|
|
459
|
-
if (exchange.type === "topic") {
|
|
460
|
-
const createConsumer$1 = (queue, routingKey) => {
|
|
461
|
-
const binding = callDefineQueueBinding(queue, exchange, routingKey ? {
|
|
462
|
-
...options,
|
|
463
|
-
routingKey
|
|
464
|
-
} : options);
|
|
465
|
-
return {
|
|
466
|
-
consumer: defineConsumer(queue, message),
|
|
467
|
-
binding
|
|
468
|
-
};
|
|
469
|
-
};
|
|
470
|
-
return {
|
|
471
|
-
publisher,
|
|
472
|
-
createConsumer: createConsumer$1
|
|
473
|
-
};
|
|
790
|
+
if (inputPublishers && Object.keys(inputPublishers).length > 0) {
|
|
791
|
+
const processedPublishers = {};
|
|
792
|
+
for (const [name, entry] of Object.entries(inputPublishers)) if (isEventPublisherConfig(entry)) {
|
|
793
|
+
const publisherOptions = {};
|
|
794
|
+
if (entry.routingKey !== void 0) publisherOptions.routingKey = entry.routingKey;
|
|
795
|
+
processedPublishers[name] = definePublisherInternal(entry.exchange, entry.message, publisherOptions);
|
|
796
|
+
} else processedPublishers[name] = entry;
|
|
797
|
+
result.publishers = processedPublishers;
|
|
474
798
|
}
|
|
475
|
-
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
* @internal
|
|
490
|
-
*/
|
|
491
|
-
function defineConsumerFirst(queue, exchange, message, options) {
|
|
492
|
-
const consumer = defineConsumer(queue, message);
|
|
493
|
-
const binding = callDefineQueueBinding(queue, exchange, options);
|
|
494
|
-
if (exchange.type === "topic") {
|
|
495
|
-
const createPublisher$1 = (routingKey) => {
|
|
496
|
-
return callDefinePublisher(exchange, message, {
|
|
497
|
-
...options,
|
|
498
|
-
routingKey
|
|
499
|
-
});
|
|
500
|
-
};
|
|
501
|
-
return {
|
|
502
|
-
consumer,
|
|
503
|
-
binding,
|
|
504
|
-
createPublisher: createPublisher$1
|
|
799
|
+
if (inputConsumers && Object.keys(inputConsumers).length > 0) {
|
|
800
|
+
const processedConsumers = {};
|
|
801
|
+
const consumerBindings = {};
|
|
802
|
+
for (const [name, entry] of Object.entries(inputConsumers)) if (isEventConsumerResult(entry)) {
|
|
803
|
+
processedConsumers[name] = entry.consumer;
|
|
804
|
+
consumerBindings[`${name}Binding`] = entry.binding;
|
|
805
|
+
} else if (isCommandConsumerConfig(entry)) {
|
|
806
|
+
processedConsumers[name] = entry.consumer;
|
|
807
|
+
consumerBindings[`${name}Binding`] = entry.binding;
|
|
808
|
+
} else processedConsumers[name] = entry;
|
|
809
|
+
result.consumers = processedConsumers;
|
|
810
|
+
if (Object.keys(consumerBindings).length > 0) result.bindings = {
|
|
811
|
+
...result.bindings,
|
|
812
|
+
...consumerBindings
|
|
505
813
|
};
|
|
506
814
|
}
|
|
507
|
-
|
|
508
|
-
return callDefinePublisher(exchange, message, options);
|
|
509
|
-
};
|
|
510
|
-
return {
|
|
511
|
-
consumer,
|
|
512
|
-
binding,
|
|
513
|
-
createPublisher
|
|
514
|
-
};
|
|
815
|
+
return result;
|
|
515
816
|
}
|
|
817
|
+
|
|
818
|
+
//#endregion
|
|
819
|
+
//#region src/builder/ttl-backoff.ts
|
|
516
820
|
/**
|
|
517
821
|
* Create TTL-backoff retry infrastructure for a queue.
|
|
518
822
|
*
|
|
@@ -578,21 +882,29 @@ function defineTtlBackoffRetryInfrastructure(queueEntry, options) {
|
|
|
578
882
|
});
|
|
579
883
|
return {
|
|
580
884
|
waitQueue,
|
|
581
|
-
waitQueueBinding:
|
|
582
|
-
mainQueueRetryBinding:
|
|
885
|
+
waitQueueBinding: defineQueueBindingInternal(waitQueue, dlx, { routingKey: waitQueueName }),
|
|
886
|
+
mainQueueRetryBinding: defineQueueBindingInternal(queue, dlx, { routingKey: queue.name })
|
|
583
887
|
};
|
|
584
888
|
}
|
|
585
889
|
|
|
586
890
|
//#endregion
|
|
891
|
+
exports.defineCommandConsumer = defineCommandConsumer;
|
|
892
|
+
exports.defineCommandPublisher = defineCommandPublisher;
|
|
587
893
|
exports.defineConsumer = defineConsumer;
|
|
588
|
-
exports.defineConsumerFirst = defineConsumerFirst;
|
|
589
894
|
exports.defineContract = defineContract;
|
|
895
|
+
exports.defineEventConsumer = defineEventConsumer;
|
|
896
|
+
exports.defineEventPublisher = defineEventPublisher;
|
|
590
897
|
exports.defineExchange = defineExchange;
|
|
591
898
|
exports.defineExchangeBinding = defineExchangeBinding;
|
|
592
899
|
exports.defineMessage = defineMessage;
|
|
593
900
|
exports.definePublisher = definePublisher;
|
|
594
|
-
exports.definePublisherFirst = definePublisherFirst;
|
|
595
901
|
exports.defineQueue = defineQueue;
|
|
596
902
|
exports.defineQueueBinding = defineQueueBinding;
|
|
903
|
+
exports.defineQuorumQueue = defineQuorumQueue;
|
|
904
|
+
exports.defineTtlBackoffQueue = defineTtlBackoffQueue;
|
|
597
905
|
exports.defineTtlBackoffRetryInfrastructure = defineTtlBackoffRetryInfrastructure;
|
|
598
|
-
exports.extractQueue = extractQueue;
|
|
906
|
+
exports.extractQueue = extractQueue;
|
|
907
|
+
exports.isCommandConsumerConfig = isCommandConsumerConfig;
|
|
908
|
+
exports.isEventConsumerResult = isEventConsumerResult;
|
|
909
|
+
exports.isEventPublisherConfig = isEventPublisherConfig;
|
|
910
|
+
exports.isQueueWithTtlBackoffInfrastructure = isQueueWithTtlBackoffInfrastructure;
|