@amqp-contract/worker 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/README.md +53 -34
- package/dist/index.cjs +205 -245
- package/dist/index.d.cts +136 -271
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +136 -271
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +205 -243
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +123 -685
- package/package.json +8 -8
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Logger, TelemetryProvider } from "@amqp-contract/core";
|
|
2
2
|
import { Future, Result } from "@swan-io/boxed";
|
|
3
3
|
import { AmqpConnectionManagerOptions, ConnectionUrl } from "amqp-connection-manager";
|
|
4
|
-
import { ConsumerDefinition, ContractDefinition, InferConsumerNames } from "@amqp-contract/contract";
|
|
4
|
+
import { ConsumerDefinition, ContractDefinition, InferConsumerNames, MessageDefinition } from "@amqp-contract/contract";
|
|
5
|
+
import { ConsumeMessage } from "amqplib";
|
|
5
6
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
7
|
|
|
7
8
|
//#region src/errors.d.ts
|
|
@@ -61,9 +62,14 @@ type HandlerError = RetryableError | NonRetryableError;
|
|
|
61
62
|
*/
|
|
62
63
|
type InferSchemaInput<TSchema extends StandardSchemaV1> = TSchema extends StandardSchemaV1<infer TInput> ? TInput : never;
|
|
63
64
|
/**
|
|
64
|
-
* Infer consumer message input type
|
|
65
|
+
* Infer consumer message payload input type
|
|
65
66
|
*/
|
|
66
|
-
type
|
|
67
|
+
type ConsumerInferPayloadInput<TConsumer extends ConsumerDefinition> = InferSchemaInput<TConsumer["message"]["payload"]>;
|
|
68
|
+
/**
|
|
69
|
+
* Infer consumer message headers input type
|
|
70
|
+
* Returns undefined if no headers schema is defined
|
|
71
|
+
*/
|
|
72
|
+
type ConsumerInferHeadersInput<TConsumer extends ConsumerDefinition> = TConsumer["message"] extends MessageDefinition<infer _TPayload, infer THeaders> ? THeaders extends StandardSchemaV1<Record<string, unknown>> ? InferSchemaInput<THeaders> : undefined : undefined;
|
|
67
73
|
/**
|
|
68
74
|
* Infer all consumers from contract
|
|
69
75
|
*/
|
|
@@ -73,133 +79,87 @@ type InferConsumers<TContract extends ContractDefinition> = NonNullable<TContrac
|
|
|
73
79
|
*/
|
|
74
80
|
type InferConsumer<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = InferConsumers<TContract>[TName];
|
|
75
81
|
/**
|
|
76
|
-
*
|
|
82
|
+
* Infer the payload type for a specific consumer
|
|
77
83
|
*/
|
|
78
|
-
type
|
|
84
|
+
type WorkerInferConsumerPayload<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferPayloadInput<InferConsumer<TContract, TName>>;
|
|
79
85
|
/**
|
|
80
|
-
*
|
|
81
|
-
* Returns
|
|
86
|
+
* Infer the headers type for a specific consumer
|
|
87
|
+
* Returns undefined if no headers schema is defined
|
|
88
|
+
*/
|
|
89
|
+
type WorkerInferConsumerHeaders<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferHeadersInput<InferConsumer<TContract, TName>>;
|
|
90
|
+
/**
|
|
91
|
+
* A consumed message containing parsed payload and headers.
|
|
82
92
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
93
|
+
* This type represents the first argument passed to consumer handlers.
|
|
94
|
+
* It contains the validated payload and (if defined in the message schema) the validated headers.
|
|
95
|
+
*
|
|
96
|
+
* @template TPayload - The inferred payload type from the message schema
|
|
97
|
+
* @template THeaders - The inferred headers type from the message schema (undefined if not defined)
|
|
86
98
|
*
|
|
87
99
|
* @example
|
|
88
100
|
* ```typescript
|
|
89
|
-
*
|
|
90
|
-
*
|
|
101
|
+
* // Handler receives the consumed message with typed payload and headers
|
|
102
|
+
* const handler = defineHandler(contract, 'processOrder', (message, rawMessage) => {
|
|
103
|
+
* console.log(message.payload.orderId); // Typed payload
|
|
104
|
+
* console.log(message.headers?.priority); // Typed headers (if defined)
|
|
105
|
+
* console.log(rawMessage.fields.deliveryTag); // Raw AMQP message
|
|
106
|
+
* return Future.value(Result.Ok(undefined));
|
|
107
|
+
* });
|
|
91
108
|
* ```
|
|
92
109
|
*/
|
|
93
|
-
type
|
|
110
|
+
type WorkerConsumedMessage<TPayload, THeaders$1 = undefined> = {
|
|
111
|
+
/** The validated message payload */
|
|
112
|
+
payload: TPayload;
|
|
113
|
+
/** The validated message headers (present only when headers schema is defined) */
|
|
114
|
+
headers: THeaders$1 extends undefined ? undefined : THeaders$1;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Infer the full consumed message type for a specific consumer.
|
|
118
|
+
* Includes both payload and headers (if defined).
|
|
119
|
+
*/
|
|
120
|
+
type WorkerInferConsumedMessage<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerConsumedMessage<WorkerInferConsumerPayload<TContract, TName>, WorkerInferConsumerHeaders<TContract, TName>>;
|
|
94
121
|
/**
|
|
95
|
-
* Safe consumer handler type for
|
|
122
|
+
* Safe consumer handler type for a specific consumer.
|
|
96
123
|
* Returns a `Future<Result<void, HandlerError>>` for explicit error handling.
|
|
97
124
|
*
|
|
125
|
+
* **Recommended over unsafe handlers** for better error control:
|
|
126
|
+
* - RetryableError: Message will be retried with exponential backoff
|
|
127
|
+
* - NonRetryableError: Message will be immediately sent to DLQ
|
|
128
|
+
*
|
|
129
|
+
* @param message - The parsed message containing validated payload and headers
|
|
130
|
+
* @param rawMessage - The raw AMQP message with all metadata (fields, properties, content)
|
|
131
|
+
*
|
|
98
132
|
* @example
|
|
99
133
|
* ```typescript
|
|
100
|
-
* const handler:
|
|
101
|
-
* (
|
|
134
|
+
* const handler: WorkerInferSafeConsumerHandler<typeof contract, 'processOrder'> =
|
|
135
|
+
* ({ payload }, rawMessage) => {
|
|
136
|
+
* console.log(payload.orderId); // Typed payload
|
|
137
|
+
* console.log(rawMessage.fields.deliveryTag); // Raw AMQP message
|
|
138
|
+
* return Future.value(Result.Ok(undefined));
|
|
139
|
+
* };
|
|
102
140
|
* ```
|
|
103
141
|
*/
|
|
104
|
-
type
|
|
142
|
+
type WorkerInferSafeConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = (message: WorkerInferConsumedMessage<TContract, TName>, rawMessage: ConsumeMessage) => Future<Result<void, HandlerError>>;
|
|
105
143
|
/**
|
|
106
144
|
* Safe handler entry for a consumer - either a function or a tuple of [handler, options].
|
|
107
145
|
*
|
|
108
|
-
*
|
|
109
|
-
* 1. Simple handler: `(
|
|
110
|
-
* 2. Handler with prefetch: `[(
|
|
111
|
-
*
|
|
146
|
+
* Two patterns are supported:
|
|
147
|
+
* 1. Simple handler: `({ payload }, rawMessage) => Future.value(Result.Ok(undefined))`
|
|
148
|
+
* 2. Handler with prefetch: `[({ payload }, rawMessage) => ..., { prefetch: 10 }]`
|
|
149
|
+
*
|
|
150
|
+
* Note: Retry configuration is now defined at the queue level in the contract,
|
|
151
|
+
* not at the handler level. See `QueueDefinition.retry` for configuration options.
|
|
112
152
|
*/
|
|
113
153
|
type WorkerInferSafeConsumerHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferSafeConsumerHandler<TContract, TName> | readonly [WorkerInferSafeConsumerHandler<TContract, TName>, {
|
|
114
154
|
prefetch?: number;
|
|
115
|
-
batchSize?: never;
|
|
116
|
-
batchTimeout?: never;
|
|
117
|
-
}] | readonly [WorkerInferSafeConsumerBatchHandler<TContract, TName>, {
|
|
118
|
-
prefetch?: number;
|
|
119
|
-
batchSize: number;
|
|
120
|
-
batchTimeout?: number;
|
|
121
155
|
}];
|
|
122
156
|
/**
|
|
123
157
|
* Safe consumer handlers for a contract.
|
|
124
158
|
* All handlers return `Future<Result<void, HandlerError>>` for explicit error control.
|
|
125
159
|
*/
|
|
126
160
|
type WorkerInferSafeConsumerHandlers<TContract extends ContractDefinition> = { [K in InferConsumerNames<TContract>]: WorkerInferSafeConsumerHandlerEntry<TContract, K> };
|
|
127
|
-
/**
|
|
128
|
-
* Unsafe consumer handler type for a specific consumer.
|
|
129
|
-
* Returns a `Promise<void>` - throws exceptions on error.
|
|
130
|
-
*
|
|
131
|
-
* @deprecated Prefer using safe handlers (WorkerInferSafeConsumerHandler) that return
|
|
132
|
-
* `Future<Result<void, HandlerError>>` for better error handling.
|
|
133
|
-
*
|
|
134
|
-
* **Note:** When using unsafe handlers:
|
|
135
|
-
* - All thrown errors are treated as retryable by default (when retry is configured)
|
|
136
|
-
* - Use RetryableError or NonRetryableError to control retry behavior explicitly
|
|
137
|
-
*/
|
|
138
|
-
type WorkerInferUnsafeConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = (message: WorkerInferConsumerInput<TContract, TName>) => Promise<void>;
|
|
139
|
-
/**
|
|
140
|
-
* Unsafe consumer handler type for batch processing.
|
|
141
|
-
* Returns a `Promise<void>` - throws exceptions on error.
|
|
142
|
-
*
|
|
143
|
-
* @deprecated Prefer using safe handlers (WorkerInferSafeConsumerBatchHandler) that return
|
|
144
|
-
* `Future<Result<void, HandlerError>>` for better error handling.
|
|
145
|
-
*/
|
|
146
|
-
type WorkerInferUnsafeConsumerBatchHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = (messages: Array<WorkerInferConsumerInput<TContract, TName>>) => Promise<void>;
|
|
147
|
-
/**
|
|
148
|
-
* Unsafe handler entry for a consumer - either a function or a tuple of [handler, options].
|
|
149
|
-
*
|
|
150
|
-
* @deprecated Prefer using safe handler entries (WorkerInferSafeConsumerHandlerEntry).
|
|
151
|
-
*/
|
|
152
|
-
type WorkerInferUnsafeConsumerHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferUnsafeConsumerHandler<TContract, TName> | readonly [WorkerInferUnsafeConsumerHandler<TContract, TName>, {
|
|
153
|
-
prefetch?: number;
|
|
154
|
-
batchSize?: never;
|
|
155
|
-
batchTimeout?: never;
|
|
156
|
-
}] | readonly [WorkerInferUnsafeConsumerBatchHandler<TContract, TName>, {
|
|
157
|
-
prefetch?: number;
|
|
158
|
-
batchSize: number;
|
|
159
|
-
batchTimeout?: number;
|
|
160
|
-
}];
|
|
161
|
-
/**
|
|
162
|
-
* Unsafe consumer handlers for a contract.
|
|
163
|
-
*
|
|
164
|
-
* @deprecated Prefer using safe handlers (WorkerInferSafeConsumerHandlers).
|
|
165
|
-
*/
|
|
166
|
-
type WorkerInferUnsafeConsumerHandlers<TContract extends ContractDefinition> = { [K in InferConsumerNames<TContract>]: WorkerInferUnsafeConsumerHandlerEntry<TContract, K> };
|
|
167
|
-
/**
|
|
168
|
-
* @deprecated Use WorkerInferUnsafeConsumerHandler instead
|
|
169
|
-
*/
|
|
170
|
-
type WorkerInferConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferUnsafeConsumerHandler<TContract, TName>;
|
|
171
|
-
/**
|
|
172
|
-
* @deprecated Use WorkerInferUnsafeConsumerBatchHandler instead
|
|
173
|
-
*/
|
|
174
|
-
type WorkerInferConsumerBatchHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferUnsafeConsumerBatchHandler<TContract, TName>;
|
|
175
|
-
/**
|
|
176
|
-
* @deprecated Use WorkerInferUnsafeConsumerHandlerEntry instead
|
|
177
|
-
*/
|
|
178
|
-
type WorkerInferConsumerHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferUnsafeConsumerHandlerEntry<TContract, TName>;
|
|
179
|
-
/**
|
|
180
|
-
* @deprecated Use WorkerInferUnsafeConsumerHandlers instead
|
|
181
|
-
*/
|
|
182
|
-
type WorkerInferConsumerHandlers<TContract extends ContractDefinition> = WorkerInferUnsafeConsumerHandlers<TContract>;
|
|
183
161
|
//#endregion
|
|
184
162
|
//#region src/worker.d.ts
|
|
185
|
-
/**
|
|
186
|
-
* Retry configuration options for handling failed message processing.
|
|
187
|
-
*
|
|
188
|
-
* When enabled, the worker will automatically retry failed messages using
|
|
189
|
-
* RabbitMQ's native TTL + Dead Letter Exchange (DLX) pattern.
|
|
190
|
-
*/
|
|
191
|
-
type RetryOptions = {
|
|
192
|
-
/** Maximum retry attempts before sending to DLQ (default: 3) */
|
|
193
|
-
maxRetries?: number;
|
|
194
|
-
/** Initial delay in ms before first retry (default: 1000) */
|
|
195
|
-
initialDelayMs?: number;
|
|
196
|
-
/** Maximum delay in ms between retries (default: 30000) */
|
|
197
|
-
maxDelayMs?: number;
|
|
198
|
-
/** Exponential backoff multiplier (default: 2) */
|
|
199
|
-
backoffMultiplier?: number;
|
|
200
|
-
/** Add jitter to prevent thundering herd (default: true) */
|
|
201
|
-
jitter?: boolean;
|
|
202
|
-
};
|
|
203
163
|
/**
|
|
204
164
|
* Options for creating a type-safe AMQP worker.
|
|
205
165
|
*
|
|
@@ -211,38 +171,29 @@ type RetryOptions = {
|
|
|
211
171
|
* contract: myContract,
|
|
212
172
|
* handlers: {
|
|
213
173
|
* // Simple handler
|
|
214
|
-
* processOrder:
|
|
215
|
-
* console.log('Processing order:',
|
|
174
|
+
* processOrder: ({ payload }) => {
|
|
175
|
+
* console.log('Processing order:', payload.orderId);
|
|
176
|
+
* return Future.value(Result.Ok(undefined));
|
|
216
177
|
* },
|
|
217
|
-
* // Handler with
|
|
178
|
+
* // Handler with prefetch configuration
|
|
218
179
|
* processPayment: [
|
|
219
|
-
*
|
|
220
|
-
* console.log('Processing payment:',
|
|
180
|
+
* ({ payload }) => {
|
|
181
|
+
* console.log('Processing payment:', payload.paymentId);
|
|
182
|
+
* return Future.value(Result.Ok(undefined));
|
|
221
183
|
* },
|
|
222
184
|
* { prefetch: 10 }
|
|
223
|
-
* ],
|
|
224
|
-
* // Handler with batch processing
|
|
225
|
-
* processNotifications: [
|
|
226
|
-
* async (messages) => {
|
|
227
|
-
* console.log('Processing batch:', messages.length);
|
|
228
|
-
* },
|
|
229
|
-
* { batchSize: 5, batchTimeout: 1000 }
|
|
230
185
|
* ]
|
|
231
186
|
* },
|
|
232
187
|
* urls: ['amqp://localhost'],
|
|
233
188
|
* connectionOptions: {
|
|
234
189
|
* heartbeatIntervalInSeconds: 30
|
|
235
190
|
* },
|
|
236
|
-
* logger: myLogger
|
|
237
|
-
* retry: {
|
|
238
|
-
* maxRetries: 3,
|
|
239
|
-
* initialDelayMs: 1000,
|
|
240
|
-
* maxDelayMs: 30000,
|
|
241
|
-
* backoffMultiplier: 2,
|
|
242
|
-
* jitter: true
|
|
243
|
-
* }
|
|
191
|
+
* logger: myLogger
|
|
244
192
|
* };
|
|
245
193
|
* ```
|
|
194
|
+
*
|
|
195
|
+
* Note: Retry configuration is defined at the queue level in the contract,
|
|
196
|
+
* not at the handler level. See `QueueDefinition.retry` for configuration options.
|
|
246
197
|
*/
|
|
247
198
|
type CreateWorkerOptions<TContract extends ContractDefinition> = {
|
|
248
199
|
/** The AMQP contract definition specifying consumers and their message schemas */
|
|
@@ -250,8 +201,7 @@ type CreateWorkerOptions<TContract extends ContractDefinition> = {
|
|
|
250
201
|
/**
|
|
251
202
|
* Handlers for each consumer defined in the contract.
|
|
252
203
|
* Handlers must return `Future<Result<void, HandlerError>>` for explicit error handling.
|
|
253
|
-
* Use defineHandler() to create
|
|
254
|
-
* Promise-based handlers into safe handlers internally.
|
|
204
|
+
* Use defineHandler() to create handlers.
|
|
255
205
|
*/
|
|
256
206
|
handlers: WorkerInferSafeConsumerHandlers<TContract>;
|
|
257
207
|
/** AMQP broker URL(s). Multiple URLs provide failover support */
|
|
@@ -260,8 +210,6 @@ type CreateWorkerOptions<TContract extends ContractDefinition> = {
|
|
|
260
210
|
connectionOptions?: AmqpConnectionManagerOptions | undefined;
|
|
261
211
|
/** Optional logger for logging message consumption and errors */
|
|
262
212
|
logger?: Logger | undefined;
|
|
263
|
-
/** Retry configuration - when undefined, uses legacy behavior (immediate requeue) */
|
|
264
|
-
retry?: RetryOptions | undefined;
|
|
265
213
|
/**
|
|
266
214
|
* Optional telemetry provider for tracing and metrics.
|
|
267
215
|
* If not provided, uses the default provider which attempts to load OpenTelemetry.
|
|
@@ -314,14 +262,11 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
314
262
|
private readonly amqpClient;
|
|
315
263
|
private readonly logger?;
|
|
316
264
|
/**
|
|
317
|
-
* Internal handler
|
|
318
|
-
* Unsafe handlers are wrapped into safe handlers by defineUnsafeHandler/defineUnsafeHandlers.
|
|
265
|
+
* Internal handler storage - handlers returning `Future<Result>`.
|
|
319
266
|
*/
|
|
320
267
|
private readonly actualHandlers;
|
|
321
268
|
private readonly consumerOptions;
|
|
322
|
-
private readonly batchTimers;
|
|
323
269
|
private readonly consumerTags;
|
|
324
|
-
private readonly retryConfig;
|
|
325
270
|
private readonly telemetry;
|
|
326
271
|
private constructor();
|
|
327
272
|
/**
|
|
@@ -343,7 +288,7 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
343
288
|
* const worker = await TypedAmqpWorker.create({
|
|
344
289
|
* contract: myContract,
|
|
345
290
|
* handlers: {
|
|
346
|
-
* processOrder: async (
|
|
291
|
+
* processOrder: async ({ payload }) => console.log('Order:', payload.orderId)
|
|
347
292
|
* },
|
|
348
293
|
* urls: ['amqp://localhost']
|
|
349
294
|
* }).resultToPromise();
|
|
@@ -355,7 +300,6 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
355
300
|
urls,
|
|
356
301
|
connectionOptions,
|
|
357
302
|
logger,
|
|
358
|
-
retry,
|
|
359
303
|
telemetry
|
|
360
304
|
}: CreateWorkerOptions<TContract>): Future<Result<TypedAmqpWorker<TContract>, TechnicalError>>;
|
|
361
305
|
/**
|
|
@@ -376,10 +320,28 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
376
320
|
*/
|
|
377
321
|
close(): Future<Result<void, TechnicalError>>;
|
|
378
322
|
/**
|
|
379
|
-
*
|
|
380
|
-
*
|
|
323
|
+
* Validate retry configuration for all consumers.
|
|
324
|
+
*
|
|
325
|
+
* For quorum-native mode, validates that the queue is properly configured.
|
|
326
|
+
* For TTL-backoff mode, wait queues are created by setupAmqpTopology in the core package.
|
|
327
|
+
*/
|
|
328
|
+
private validateRetryConfiguration;
|
|
329
|
+
/**
|
|
330
|
+
* Get the resolved retry configuration for a consumer's queue.
|
|
331
|
+
* Reads retry config from the queue definition in the contract.
|
|
332
|
+
*/
|
|
333
|
+
private getRetryConfigForConsumer;
|
|
334
|
+
/**
|
|
335
|
+
* Validate that quorum-native retry mode is properly configured for a specific consumer.
|
|
336
|
+
*
|
|
337
|
+
* Requirements for quorum-native mode:
|
|
338
|
+
* - Consumer queue must be a quorum queue
|
|
339
|
+
* - Consumer queue must have deliveryLimit configured
|
|
340
|
+
* - Consumer queue should have DLX configured (warning if not)
|
|
341
|
+
*
|
|
342
|
+
* @returns TechnicalError if validation fails, null if valid
|
|
381
343
|
*/
|
|
382
|
-
private
|
|
344
|
+
private validateQuorumNativeConfigForConsumer;
|
|
383
345
|
/**
|
|
384
346
|
* Start consuming messages for all consumers
|
|
385
347
|
*/
|
|
@@ -391,31 +353,45 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
391
353
|
private consume;
|
|
392
354
|
/**
|
|
393
355
|
* Parse and validate a message from AMQP
|
|
394
|
-
* @returns `Future<Result<
|
|
356
|
+
* @returns `Future<Result<consumed message, void>>` - Ok with validated consumed message (payload + headers), or Error (already handled with nack)
|
|
395
357
|
*/
|
|
396
358
|
private parseAndValidateMessage;
|
|
397
359
|
/**
|
|
398
360
|
* Consume messages one at a time
|
|
399
361
|
*/
|
|
400
362
|
private consumeSingle;
|
|
401
|
-
/**
|
|
402
|
-
* Handle batch processing error by applying error handling to all messages.
|
|
403
|
-
*/
|
|
404
|
-
private handleBatchError;
|
|
405
|
-
/**
|
|
406
|
-
* Consume messages in batches
|
|
407
|
-
*/
|
|
408
|
-
private consumeBatch;
|
|
409
363
|
/**
|
|
410
364
|
* Handle error in message processing with retry logic.
|
|
411
365
|
*
|
|
412
|
-
* Flow:
|
|
366
|
+
* Flow depends on retry mode:
|
|
367
|
+
*
|
|
368
|
+
* **quorum-native mode:**
|
|
369
|
+
* 1. If NonRetryableError -> send directly to DLQ (no retry)
|
|
370
|
+
* 2. Otherwise -> nack with requeue=true (RabbitMQ handles delivery count)
|
|
371
|
+
*
|
|
372
|
+
* **ttl-backoff mode:**
|
|
413
373
|
* 1. If NonRetryableError -> send directly to DLQ (no retry)
|
|
414
|
-
* 2. If
|
|
415
|
-
* 3.
|
|
416
|
-
*
|
|
374
|
+
* 2. If max retries exceeded -> send to DLQ
|
|
375
|
+
* 3. Otherwise -> publish to wait queue with TTL for retry
|
|
376
|
+
*
|
|
377
|
+
* **Legacy mode (no retry config):**
|
|
378
|
+
* 1. nack with requeue=true (immediate requeue)
|
|
417
379
|
*/
|
|
418
380
|
private handleError;
|
|
381
|
+
/**
|
|
382
|
+
* Handle error using quorum queue's native delivery limit feature.
|
|
383
|
+
*
|
|
384
|
+
* Simply requeues the message with nack(requeue=true). RabbitMQ automatically:
|
|
385
|
+
* - Increments x-delivery-count header
|
|
386
|
+
* - Dead-letters the message when count exceeds x-delivery-limit
|
|
387
|
+
*
|
|
388
|
+
* This is simpler than TTL-based retry but provides immediate retries only.
|
|
389
|
+
*/
|
|
390
|
+
private handleErrorQuorumNative;
|
|
391
|
+
/**
|
|
392
|
+
* Handle error using TTL + wait queue pattern for exponential backoff.
|
|
393
|
+
*/
|
|
394
|
+
private handleErrorTtlBackoff;
|
|
419
395
|
/**
|
|
420
396
|
* Calculate retry delay with exponential backoff and optional jitter.
|
|
421
397
|
*/
|
|
@@ -465,17 +441,16 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
465
441
|
* **Recommended:** This function creates handlers that return `Future<Result<void, HandlerError>>`,
|
|
466
442
|
* providing explicit error handling and better control over retry behavior.
|
|
467
443
|
*
|
|
468
|
-
* Supports
|
|
469
|
-
* 1. Simple handler: just the function
|
|
470
|
-
* 2. Handler with
|
|
471
|
-
* 3. Batch handler: [batchHandler, { batchSize: 5, batchTimeout: 1000 }] (REQUIRES batchSize config)
|
|
444
|
+
* Supports two patterns:
|
|
445
|
+
* 1. Simple handler: just the function
|
|
446
|
+
* 2. Handler with options: [handler, { prefetch: 10 }]
|
|
472
447
|
*
|
|
473
448
|
* @template TContract - The contract definition type
|
|
474
449
|
* @template TName - The consumer name from the contract
|
|
475
450
|
* @param contract - The contract definition containing the consumer
|
|
476
451
|
* @param consumerName - The name of the consumer from the contract
|
|
477
452
|
* @param handler - The handler function that returns `Future<Result<void, HandlerError>>`
|
|
478
|
-
* @param options - Optional consumer options (prefetch
|
|
453
|
+
* @param options - Optional consumer options (prefetch)
|
|
479
454
|
* @returns A type-safe handler that can be used with TypedAmqpWorker
|
|
480
455
|
*
|
|
481
456
|
* @example
|
|
@@ -488,8 +463,8 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
488
463
|
* const processOrderHandler = defineHandler(
|
|
489
464
|
* orderContract,
|
|
490
465
|
* 'processOrder',
|
|
491
|
-
* (
|
|
492
|
-
* Future.fromPromise(processPayment(
|
|
466
|
+
* ({ payload }) =>
|
|
467
|
+
* Future.fromPromise(processPayment(payload))
|
|
493
468
|
* .mapOk(() => undefined)
|
|
494
469
|
* .mapError((error) => new RetryableError('Payment failed', error))
|
|
495
470
|
* );
|
|
@@ -498,8 +473,8 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
498
473
|
* const validateOrderHandler = defineHandler(
|
|
499
474
|
* orderContract,
|
|
500
475
|
* 'validateOrder',
|
|
501
|
-
* (
|
|
502
|
-
* if (
|
|
476
|
+
* ({ payload }) => {
|
|
477
|
+
* if (payload.amount < 1) {
|
|
503
478
|
* // Won't be retried - goes directly to DLQ
|
|
504
479
|
* return Future.value(Result.Error(new NonRetryableError('Invalid order amount')));
|
|
505
480
|
* }
|
|
@@ -511,13 +486,6 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
511
486
|
declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferSafeConsumerHandler<TContract, TName>): WorkerInferSafeConsumerHandlerEntry<TContract, TName>;
|
|
512
487
|
declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferSafeConsumerHandler<TContract, TName>, options: {
|
|
513
488
|
prefetch?: number;
|
|
514
|
-
batchSize?: never;
|
|
515
|
-
batchTimeout?: never;
|
|
516
|
-
}): WorkerInferSafeConsumerHandlerEntry<TContract, TName>;
|
|
517
|
-
declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferSafeConsumerBatchHandler<TContract, TName>, options: {
|
|
518
|
-
prefetch?: number;
|
|
519
|
-
batchSize: number;
|
|
520
|
-
batchTimeout?: number;
|
|
521
489
|
}): WorkerInferSafeConsumerHandlerEntry<TContract, TName>;
|
|
522
490
|
/**
|
|
523
491
|
* Define multiple type-safe handlers for consumers in a contract.
|
|
@@ -537,121 +505,18 @@ declare function defineHandler<TContract extends ContractDefinition, TName exten
|
|
|
537
505
|
* import { orderContract } from './contract';
|
|
538
506
|
*
|
|
539
507
|
* const handlers = defineHandlers(orderContract, {
|
|
540
|
-
* processOrder: (
|
|
541
|
-
* Future.fromPromise(processPayment(
|
|
508
|
+
* processOrder: ({ payload }) =>
|
|
509
|
+
* Future.fromPromise(processPayment(payload))
|
|
542
510
|
* .mapOk(() => undefined)
|
|
543
511
|
* .mapError((error) => new RetryableError('Payment failed', error)),
|
|
544
|
-
* notifyOrder: (
|
|
545
|
-
* Future.fromPromise(sendNotification(
|
|
512
|
+
* notifyOrder: ({ payload }) =>
|
|
513
|
+
* Future.fromPromise(sendNotification(payload))
|
|
546
514
|
* .mapOk(() => undefined)
|
|
547
515
|
* .mapError((error) => new RetryableError('Notification failed', error)),
|
|
548
516
|
* });
|
|
549
517
|
* ```
|
|
550
518
|
*/
|
|
551
519
|
declare function defineHandlers<TContract extends ContractDefinition>(contract: TContract, handlers: WorkerInferSafeConsumerHandlers<TContract>): WorkerInferSafeConsumerHandlers<TContract>;
|
|
552
|
-
/**
|
|
553
|
-
* Unsafe handler type for single messages (internal use).
|
|
554
|
-
*/
|
|
555
|
-
type UnsafeHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = (message: WorkerInferConsumerInput<TContract, TName>) => Promise<void>;
|
|
556
|
-
/**
|
|
557
|
-
* Unsafe handler type for batch messages (internal use).
|
|
558
|
-
*/
|
|
559
|
-
type UnsafeBatchHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = (messages: Array<WorkerInferConsumerInput<TContract, TName>>) => Promise<void>;
|
|
560
|
-
/**
|
|
561
|
-
* Define an unsafe handler for a specific consumer in a contract.
|
|
562
|
-
*
|
|
563
|
-
* @deprecated Use `defineHandler` instead for explicit error handling with `Future<Result>`.
|
|
564
|
-
*
|
|
565
|
-
* **Warning:** Unsafe handlers use exception-based error handling:
|
|
566
|
-
* - All thrown errors are treated as retryable by default
|
|
567
|
-
* - Harder to reason about which errors should be retried
|
|
568
|
-
* - May lead to unexpected retry behavior
|
|
569
|
-
*
|
|
570
|
-
* **Note:** Internally, this function wraps the Promise-based handler into a Future-based
|
|
571
|
-
* safe handler for consistent processing in the worker.
|
|
572
|
-
*
|
|
573
|
-
* @template TContract - The contract definition type
|
|
574
|
-
* @template TName - The consumer name from the contract
|
|
575
|
-
* @param contract - The contract definition containing the consumer
|
|
576
|
-
* @param consumerName - The name of the consumer from the contract
|
|
577
|
-
* @param handler - The async handler function that processes messages
|
|
578
|
-
* @param options - Optional consumer options (prefetch, batchSize, batchTimeout)
|
|
579
|
-
* @returns A type-safe handler that can be used with TypedAmqpWorker
|
|
580
|
-
*
|
|
581
|
-
* @example
|
|
582
|
-
* ```typescript
|
|
583
|
-
* import { defineUnsafeHandler } from '@amqp-contract/worker';
|
|
584
|
-
*
|
|
585
|
-
* // ⚠️ Consider using defineHandler for better error handling
|
|
586
|
-
* const processOrderHandler = defineUnsafeHandler(
|
|
587
|
-
* orderContract,
|
|
588
|
-
* 'processOrder',
|
|
589
|
-
* async (message) => {
|
|
590
|
-
* // Throws on error - will be retried
|
|
591
|
-
* await processPayment(message);
|
|
592
|
-
* }
|
|
593
|
-
* );
|
|
594
|
-
* ```
|
|
595
|
-
*/
|
|
596
|
-
declare function defineUnsafeHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: UnsafeHandler<TContract, TName>): WorkerInferSafeConsumerHandlerEntry<TContract, TName>;
|
|
597
|
-
declare function defineUnsafeHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: UnsafeHandler<TContract, TName>, options: {
|
|
598
|
-
prefetch?: number;
|
|
599
|
-
batchSize?: never;
|
|
600
|
-
batchTimeout?: never;
|
|
601
|
-
}): WorkerInferSafeConsumerHandlerEntry<TContract, TName>;
|
|
602
|
-
declare function defineUnsafeHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: UnsafeBatchHandler<TContract, TName>, options: {
|
|
603
|
-
prefetch?: number;
|
|
604
|
-
batchSize: number;
|
|
605
|
-
batchTimeout?: number;
|
|
606
|
-
}): WorkerInferSafeConsumerHandlerEntry<TContract, TName>;
|
|
607
|
-
/**
|
|
608
|
-
* Unsafe handler entry type for internal use.
|
|
609
|
-
*/
|
|
610
|
-
type UnsafeHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = UnsafeHandler<TContract, TName> | readonly [UnsafeHandler<TContract, TName>, {
|
|
611
|
-
prefetch?: number;
|
|
612
|
-
batchSize?: never;
|
|
613
|
-
batchTimeout?: never;
|
|
614
|
-
}] | readonly [UnsafeBatchHandler<TContract, TName>, {
|
|
615
|
-
prefetch?: number;
|
|
616
|
-
batchSize: number;
|
|
617
|
-
batchTimeout?: number;
|
|
618
|
-
}];
|
|
619
|
-
/**
|
|
620
|
-
* Unsafe handlers object type for internal use.
|
|
621
|
-
*/
|
|
622
|
-
type UnsafeHandlers<TContract extends ContractDefinition> = { [K in InferConsumerNames<TContract>]: UnsafeHandlerEntry<TContract, K> };
|
|
623
|
-
/**
|
|
624
|
-
* Define multiple unsafe handlers for consumers in a contract.
|
|
625
|
-
*
|
|
626
|
-
* @deprecated Use `defineHandlers` instead for explicit error handling with `Future<Result>`.
|
|
627
|
-
*
|
|
628
|
-
* **Warning:** Unsafe handlers use exception-based error handling.
|
|
629
|
-
* Consider migrating to safe handlers for better error control.
|
|
630
|
-
*
|
|
631
|
-
* **Note:** Internally, this function wraps all Promise-based handlers into Future-based
|
|
632
|
-
* safe handlers for consistent processing in the worker.
|
|
633
|
-
*
|
|
634
|
-
* @template TContract - The contract definition type
|
|
635
|
-
* @param contract - The contract definition containing the consumers
|
|
636
|
-
* @param handlers - An object with async handler functions for each consumer
|
|
637
|
-
* @returns A type-safe handlers object that can be used with TypedAmqpWorker
|
|
638
|
-
*
|
|
639
|
-
* @example
|
|
640
|
-
* ```typescript
|
|
641
|
-
* import { defineUnsafeHandlers } from '@amqp-contract/worker';
|
|
642
|
-
*
|
|
643
|
-
* // ⚠️ Consider using defineHandlers for better error handling
|
|
644
|
-
* const handlers = defineUnsafeHandlers(orderContract, {
|
|
645
|
-
* processOrder: async (message) => {
|
|
646
|
-
* await processPayment(message);
|
|
647
|
-
* },
|
|
648
|
-
* notifyOrder: async (message) => {
|
|
649
|
-
* await sendNotification(message);
|
|
650
|
-
* },
|
|
651
|
-
* });
|
|
652
|
-
* ```
|
|
653
|
-
*/
|
|
654
|
-
declare function defineUnsafeHandlers<TContract extends ContractDefinition>(contract: TContract, handlers: UnsafeHandlers<TContract>): WorkerInferSafeConsumerHandlers<TContract>;
|
|
655
520
|
//#endregion
|
|
656
|
-
export { type CreateWorkerOptions, type HandlerError, MessageValidationError, NonRetryableError,
|
|
521
|
+
export { type CreateWorkerOptions, type HandlerError, MessageValidationError, NonRetryableError, RetryableError, TechnicalError, TypedAmqpWorker, type WorkerConsumedMessage, type WorkerInferConsumedMessage, type WorkerInferConsumerHeaders, type WorkerInferSafeConsumerHandler, type WorkerInferSafeConsumerHandlerEntry, type WorkerInferSafeConsumerHandlers, defineHandler, defineHandlers };
|
|
657
522
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/worker.ts","../src/handlers.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/worker.ts","../src/handlers.ts"],"sourcesContent":[],"mappings":"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"}
|