@amqp-contract/worker 0.20.0 → 0.22.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 +6 -7
- package/dist/index.cjs +415 -291
- package/dist/index.d.cts +123 -149
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +122 -148
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +409 -284
- package/dist/index.mjs.map +1 -1
- package/docs/index.md +90 -115
- package/package.json +29 -29
package/dist/index.d.cts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConsumerDefinition, ConsumerEntry, ContractDefinition, InferConsumerNames, InferRpcNames, MessageDefinition, RpcDefinition } from "@amqp-contract/contract";
|
|
2
|
+
import { ConsumerOptions as ConsumerOptions$1, Logger, MessageValidationError, TechnicalError, TelemetryProvider } from "@amqp-contract/core";
|
|
3
|
+
import { Future, Result } from "@swan-io/boxed";
|
|
2
4
|
import * as amqp from "amqplib";
|
|
3
5
|
import { ConsumeMessage } from "amqplib";
|
|
4
6
|
import { TcpSocketConnectOpts } from "net";
|
|
5
7
|
import { ConnectionOptions } from "tls";
|
|
6
|
-
import { ConsumerDefinition, ConsumerEntry, ContractDefinition, InferConsumerNames, MessageDefinition } from "@amqp-contract/contract";
|
|
7
|
-
import { Future, Result } from "@swan-io/boxed";
|
|
8
8
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
9
9
|
|
|
10
|
-
//#region ../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@0.
|
|
10
|
+
//#region ../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@1.0.3/node_modules/amqp-connection-manager/dist/types/AmqpConnectionManager.d.ts
|
|
11
11
|
type ConnectionUrl = string | amqp.Options.Connect | {
|
|
12
12
|
url: string;
|
|
13
13
|
connectionOptions?: AmqpConnectionOptions;
|
|
@@ -196,9 +196,9 @@ declare function nonRetryable(message: string, cause?: unknown): NonRetryableErr
|
|
|
196
196
|
//#endregion
|
|
197
197
|
//#region src/types.d.ts
|
|
198
198
|
/**
|
|
199
|
-
* Infer the
|
|
199
|
+
* Infer the output type from a schema (used by consumers after validation)
|
|
200
200
|
*/
|
|
201
|
-
type
|
|
201
|
+
type InferSchemaOutput<TSchema extends StandardSchemaV1> = TSchema extends StandardSchemaV1<infer _TInput, infer TOutput> ? TOutput : never;
|
|
202
202
|
/**
|
|
203
203
|
* Extract the ConsumerDefinition from any consumer entry type.
|
|
204
204
|
* Handles ConsumerDefinition, EventConsumerResult, and CommandConsumerConfig.
|
|
@@ -207,32 +207,42 @@ type ExtractConsumerDefinition<T extends ConsumerEntry> = T extends ConsumerDefi
|
|
|
207
207
|
consumer: ConsumerDefinition;
|
|
208
208
|
} ? T["consumer"] : never;
|
|
209
209
|
/**
|
|
210
|
-
* Infer consumer message payload
|
|
210
|
+
* Infer consumer message payload output type.
|
|
211
211
|
* Works with any consumer entry type by first extracting the ConsumerDefinition.
|
|
212
212
|
*/
|
|
213
|
-
type
|
|
213
|
+
type ConsumerInferPayloadOutput<TConsumer extends ConsumerEntry> = ExtractConsumerDefinition<TConsumer> extends ConsumerDefinition ? InferSchemaOutput<ExtractConsumerDefinition<TConsumer>["message"]["payload"]> : never;
|
|
214
214
|
/**
|
|
215
|
-
* Infer consumer message headers
|
|
216
|
-
* Returns undefined if no headers schema is defined
|
|
215
|
+
* Infer consumer message headers output type.
|
|
216
|
+
* Returns undefined if no headers schema is defined.
|
|
217
217
|
*/
|
|
218
|
-
type
|
|
218
|
+
type ConsumerInferHeadersOutput<TConsumer extends ConsumerEntry> = ExtractConsumerDefinition<TConsumer> extends ConsumerDefinition ? ExtractConsumerDefinition<TConsumer>["message"] extends MessageDefinition<infer _TPayload, infer THeaders> ? THeaders extends StandardSchemaV1<Record<string, unknown>> ? InferSchemaOutput<THeaders> : undefined : undefined : undefined;
|
|
219
|
+
type InferConsumers<TContract extends ContractDefinition> = NonNullable<TContract["consumers"]>;
|
|
220
|
+
type InferConsumer<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = InferConsumers<TContract>[TName];
|
|
221
|
+
type InferRpcs<TContract extends ContractDefinition> = NonNullable<TContract["rpcs"]>;
|
|
222
|
+
type InferRpc<TContract extends ContractDefinition, TName extends InferRpcNames<TContract>> = InferRpcs<TContract>[TName];
|
|
219
223
|
/**
|
|
220
|
-
* Infer
|
|
224
|
+
* Infer the payload type for a regular consumer (validated against the message schema).
|
|
221
225
|
*/
|
|
222
|
-
type
|
|
226
|
+
type WorkerInferConsumerPayload<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferPayloadOutput<InferConsumer<TContract, TName>>;
|
|
223
227
|
/**
|
|
224
|
-
*
|
|
228
|
+
* Infer the headers type for a regular consumer.
|
|
229
|
+
* Returns undefined if no headers schema is defined.
|
|
225
230
|
*/
|
|
226
|
-
type
|
|
231
|
+
type WorkerInferConsumerHeaders<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = ConsumerInferHeadersOutput<InferConsumer<TContract, TName>>;
|
|
232
|
+
/**
|
|
233
|
+
* Infer the request payload type for an RPC.
|
|
234
|
+
*/
|
|
235
|
+
type WorkerInferRpcRequest<TContract extends ContractDefinition, TName extends InferRpcNames<TContract>> = InferRpc<TContract, TName> extends RpcDefinition<infer TRequest, MessageDefinition> ? TRequest extends MessageDefinition ? InferSchemaOutput<TRequest["payload"]> : never : never;
|
|
227
236
|
/**
|
|
228
|
-
* Infer the
|
|
237
|
+
* Infer the request headers type for an RPC. Returns undefined unless the RPC's
|
|
238
|
+
* request `MessageDefinition` declares a headers schema.
|
|
229
239
|
*/
|
|
230
|
-
type
|
|
240
|
+
type WorkerInferRpcHeaders<TContract extends ContractDefinition, TName extends InferRpcNames<TContract>> = InferRpc<TContract, TName> extends RpcDefinition<infer TRequest, MessageDefinition> ? TRequest extends MessageDefinition<infer _TPayload, infer THeaders> ? THeaders extends StandardSchemaV1<Record<string, unknown>> ? InferSchemaOutput<THeaders> : undefined : undefined : undefined;
|
|
231
241
|
/**
|
|
232
|
-
* Infer the
|
|
233
|
-
*
|
|
242
|
+
* Infer the response payload type for an RPC. The handler must return a
|
|
243
|
+
* `Future<Result<TResponse, HandlerError>>` matching this shape.
|
|
234
244
|
*/
|
|
235
|
-
type
|
|
245
|
+
type WorkerInferRpcResponse<TContract extends ContractDefinition, TName extends InferRpcNames<TContract>> = InferRpc<TContract, TName> extends RpcDefinition<MessageDefinition, infer TResponse> ? TResponse extends MessageDefinition ? InferSchemaOutput<TResponse["payload"]> : never : never;
|
|
236
246
|
/**
|
|
237
247
|
* A consumed message containing parsed payload and headers.
|
|
238
248
|
*
|
|
@@ -244,7 +254,6 @@ type WorkerInferConsumerHeaders<TContract extends ContractDefinition, TName exte
|
|
|
244
254
|
*
|
|
245
255
|
* @example
|
|
246
256
|
* ```typescript
|
|
247
|
-
* // Handler receives the consumed message with typed payload and headers
|
|
248
257
|
* const handler = defineHandler(contract, 'processOrder', (message, rawMessage) => {
|
|
249
258
|
* console.log(message.payload.orderId); // Typed payload
|
|
250
259
|
* console.log(message.headers?.priority); // Typed headers (if defined)
|
|
@@ -258,65 +267,60 @@ type WorkerConsumedMessage<TPayload, THeaders = undefined> = {
|
|
|
258
267
|
headers: THeaders extends undefined ? undefined : THeaders;
|
|
259
268
|
};
|
|
260
269
|
/**
|
|
261
|
-
* Infer the full consumed message type for a
|
|
262
|
-
* Includes both payload and headers (if defined).
|
|
270
|
+
* Infer the full consumed message type for a regular consumer.
|
|
263
271
|
*/
|
|
264
272
|
type WorkerInferConsumedMessage<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerConsumedMessage<WorkerInferConsumerPayload<TContract, TName>, WorkerInferConsumerHeaders<TContract, TName>>;
|
|
265
273
|
/**
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
* The `WorkerInfer*` naming pattern indicates type inference helpers that extract
|
|
274
|
-
* types from a contract definition at compile time.
|
|
275
|
-
*
|
|
276
|
-
* @param message - The parsed message containing validated payload and headers
|
|
277
|
-
* @param rawMessage - The raw AMQP message with all metadata (fields, properties, content)
|
|
278
|
-
*
|
|
279
|
-
* @example
|
|
280
|
-
* ```typescript
|
|
281
|
-
* const handler: WorkerInferConsumerHandler<typeof contract, 'processOrder'> =
|
|
282
|
-
* ({ payload }, rawMessage) => {
|
|
283
|
-
* console.log(payload.orderId); // Typed payload
|
|
284
|
-
* console.log(rawMessage.fields.deliveryTag); // Raw AMQP message
|
|
285
|
-
* return Future.value(Result.Ok(undefined));
|
|
286
|
-
* };
|
|
287
|
-
* ```
|
|
274
|
+
* Infer the consumed message type for an RPC handler — payload + headers from
|
|
275
|
+
* the request side of the RPC.
|
|
276
|
+
*/
|
|
277
|
+
type WorkerInferRpcConsumedMessage<TContract extends ContractDefinition, TName extends InferRpcNames<TContract>> = WorkerConsumedMessage<WorkerInferRpcRequest<TContract, TName>, WorkerInferRpcHeaders<TContract, TName>>;
|
|
278
|
+
/**
|
|
279
|
+
* Handler signature for a regular consumer (event/command). Returns
|
|
280
|
+
* `Future<Result<void, HandlerError>>` — there is no response message.
|
|
288
281
|
*/
|
|
289
282
|
type WorkerInferConsumerHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = (message: WorkerInferConsumedMessage<TContract, TName>, rawMessage: ConsumeMessage) => Future<Result<void, HandlerError>>;
|
|
290
283
|
/**
|
|
291
|
-
* Handler
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
* Note: Retry configuration is now defined at the queue level in the contract,
|
|
298
|
-
* not at the handler level. See `QueueDefinition.retry` for configuration options.
|
|
284
|
+
* Handler signature for an RPC. Returns
|
|
285
|
+
* `Future<Result<TResponse, HandlerError>>` where `TResponse` is the inferred
|
|
286
|
+
* response payload. The worker validates the response against the RPC's
|
|
287
|
+
* response schema and publishes it back to `msg.properties.replyTo` with the
|
|
288
|
+
* same `correlationId`.
|
|
299
289
|
*/
|
|
300
|
-
type
|
|
301
|
-
prefetch?: number;
|
|
302
|
-
}];
|
|
290
|
+
type WorkerInferRpcHandler<TContract extends ContractDefinition, TName extends InferRpcNames<TContract>> = (message: WorkerInferRpcConsumedMessage<TContract, TName>, rawMessage: ConsumeMessage) => Future<Result<WorkerInferRpcResponse<TContract, TName>, HandlerError>>;
|
|
303
291
|
/**
|
|
304
|
-
*
|
|
305
|
-
|
|
292
|
+
* Handler entry for a regular consumer — function or `[handler, options]`.
|
|
293
|
+
*/
|
|
294
|
+
type WorkerInferConsumerHandlerEntry<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>> = WorkerInferConsumerHandler<TContract, TName> | readonly [WorkerInferConsumerHandler<TContract, TName>, ConsumerOptions];
|
|
295
|
+
/**
|
|
296
|
+
* Handler entry for an RPC — function or `[handler, options]`.
|
|
297
|
+
*/
|
|
298
|
+
type WorkerInferRpcHandlerEntry<TContract extends ContractDefinition, TName extends InferRpcNames<TContract>> = WorkerInferRpcHandler<TContract, TName> | readonly [WorkerInferRpcHandler<TContract, TName>, ConsumerOptions];
|
|
299
|
+
/**
|
|
300
|
+
* All handlers for a contract: one entry per `consumers` key plus one entry
|
|
301
|
+
* per `rpcs` key. The two name spaces are disjoint so the resulting object
|
|
302
|
+
* type is unambiguous.
|
|
306
303
|
*
|
|
307
304
|
* @example
|
|
308
305
|
* ```typescript
|
|
309
|
-
* const handlers:
|
|
306
|
+
* const handlers: WorkerInferHandlers<typeof contract> = {
|
|
310
307
|
* processOrder: ({ payload }) =>
|
|
311
308
|
* Future.fromPromise(processPayment(payload))
|
|
312
309
|
* .mapOk(() => undefined)
|
|
313
310
|
* .mapError((error) => new RetryableError('Payment failed', error)),
|
|
311
|
+
* calculate: ({ payload }) =>
|
|
312
|
+
* Future.value(Result.Ok({ sum: payload.a + payload.b })),
|
|
314
313
|
* };
|
|
315
314
|
* ```
|
|
316
315
|
*/
|
|
317
|
-
type
|
|
316
|
+
type WorkerInferHandlers<TContract extends ContractDefinition> = ([InferConsumerNames<TContract>] extends [never] ? {} : { [K in InferConsumerNames<TContract>]: WorkerInferConsumerHandlerEntry<TContract, K> }) & ([InferRpcNames<TContract>] extends [never] ? {} : { [K in InferRpcNames<TContract>]: WorkerInferRpcHandlerEntry<TContract, K> });
|
|
317
|
+
/**
|
|
318
|
+
* @deprecated Use `WorkerInferHandlers` — handlers now span consumers ∪ rpcs.
|
|
319
|
+
*/
|
|
320
|
+
type WorkerInferConsumerHandlers<TContract extends ContractDefinition> = WorkerInferHandlers<TContract>;
|
|
318
321
|
//#endregion
|
|
319
322
|
//#region src/worker.d.ts
|
|
323
|
+
type ConsumerOptions = ConsumerOptions$1;
|
|
320
324
|
/**
|
|
321
325
|
* Options for creating a type-safe AMQP worker.
|
|
322
326
|
*
|
|
@@ -342,6 +346,9 @@ type WorkerInferConsumerHandlers<TContract extends ContractDefinition> = { [K in
|
|
|
342
346
|
* ]
|
|
343
347
|
* },
|
|
344
348
|
* urls: ['amqp://localhost'],
|
|
349
|
+
* defaultConsumerOptions: {
|
|
350
|
+
* prefetch: 5,
|
|
351
|
+
* },
|
|
345
352
|
* connectionOptions: {
|
|
346
353
|
* heartbeatIntervalInSeconds: 30
|
|
347
354
|
* },
|
|
@@ -355,11 +362,16 @@ type WorkerInferConsumerHandlers<TContract extends ContractDefinition> = { [K in
|
|
|
355
362
|
type CreateWorkerOptions<TContract extends ContractDefinition> = {
|
|
356
363
|
/** The AMQP contract definition specifying consumers and their message schemas */contract: TContract;
|
|
357
364
|
/**
|
|
358
|
-
* Handlers for each
|
|
359
|
-
*
|
|
360
|
-
*
|
|
365
|
+
* Handlers for each `consumers` and `rpcs` entry in the contract.
|
|
366
|
+
*
|
|
367
|
+
* - Regular consumers return `Future<Result<void, HandlerError>>`.
|
|
368
|
+
* - RPC handlers return `Future<Result<TResponse, HandlerError>>` where
|
|
369
|
+
* `TResponse` is inferred from the RPC's response message schema.
|
|
370
|
+
*
|
|
371
|
+
* Use `defineHandler` / `defineHandlers` to create handlers with full type
|
|
372
|
+
* inference.
|
|
361
373
|
*/
|
|
362
|
-
handlers:
|
|
374
|
+
handlers: WorkerInferHandlers<TContract>; /** AMQP broker URL(s). Multiple URLs provide failover support */
|
|
363
375
|
urls: ConnectionUrl[]; /** Optional connection configuration (heartbeat, reconnect settings, etc.) */
|
|
364
376
|
connectionOptions?: AmqpConnectionManagerOptions | undefined; /** Optional logger for logging message consumption and errors */
|
|
365
377
|
logger?: Logger | undefined;
|
|
@@ -369,6 +381,18 @@ type CreateWorkerOptions<TContract extends ContractDefinition> = {
|
|
|
369
381
|
* OpenTelemetry instrumentation is automatically enabled if @opentelemetry/api is installed.
|
|
370
382
|
*/
|
|
371
383
|
telemetry?: TelemetryProvider | undefined;
|
|
384
|
+
/**
|
|
385
|
+
* Optional default consumer options applied to all consumer handlers.
|
|
386
|
+
* Handler-specific options provided in tuple form override these defaults.
|
|
387
|
+
*/
|
|
388
|
+
defaultConsumerOptions?: ConsumerOptions | undefined;
|
|
389
|
+
/**
|
|
390
|
+
* Maximum time in ms to wait for the AMQP connection to become ready before
|
|
391
|
+
* `create()` resolves to `Result.Error<TechnicalError>`. Without this option,
|
|
392
|
+
* `create()` waits forever — the underlying amqp-connection-manager retries
|
|
393
|
+
* indefinitely.
|
|
394
|
+
*/
|
|
395
|
+
connectTimeoutMs?: number | undefined;
|
|
372
396
|
};
|
|
373
397
|
/**
|
|
374
398
|
* Type-safe AMQP worker for consuming messages from RabbitMQ.
|
|
@@ -384,7 +408,7 @@ type CreateWorkerOptions<TContract extends ContractDefinition> = {
|
|
|
384
408
|
* import { defineQueue, defineMessage, defineContract, defineConsumer } from '@amqp-contract/contract';
|
|
385
409
|
* import { z } from 'zod';
|
|
386
410
|
*
|
|
387
|
-
* const orderQueue = defineQueue('order-processing'
|
|
411
|
+
* const orderQueue = defineQueue('order-processing');
|
|
388
412
|
* const orderMessage = defineMessage(z.object({
|
|
389
413
|
* orderId: z.string(),
|
|
390
414
|
* amount: z.number()
|
|
@@ -414,15 +438,27 @@ type CreateWorkerOptions<TContract extends ContractDefinition> = {
|
|
|
414
438
|
declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
415
439
|
private readonly contract;
|
|
416
440
|
private readonly amqpClient;
|
|
441
|
+
private readonly defaultConsumerOptions;
|
|
417
442
|
private readonly logger?;
|
|
418
443
|
/**
|
|
419
|
-
* Internal handler storage
|
|
444
|
+
* Internal handler storage. Keyed by handler name (consumer or RPC); the
|
|
445
|
+
* stored function signature is widened so the dispatch loop can call it
|
|
446
|
+
* uniformly. The actual handler is type-checked at the worker's public API
|
|
447
|
+
* boundary via `WorkerInferHandlers<TContract>`.
|
|
420
448
|
*/
|
|
421
449
|
private readonly actualHandlers;
|
|
422
450
|
private readonly consumerOptions;
|
|
423
451
|
private readonly consumerTags;
|
|
424
452
|
private readonly telemetry;
|
|
425
453
|
private constructor();
|
|
454
|
+
/**
|
|
455
|
+
* Build a `ConsumerDefinition`-shaped view for a handler name, regardless
|
|
456
|
+
* of whether it came from `contract.consumers` or `contract.rpcs`. The
|
|
457
|
+
* dispatch path treats both uniformly; the returned `isRpc` flag (and the
|
|
458
|
+
* accompanying `responseSchema`) tells `processMessage` whether to validate
|
|
459
|
+
* the handler return value and publish a reply.
|
|
460
|
+
*/
|
|
461
|
+
private resolveConsumerView;
|
|
426
462
|
/**
|
|
427
463
|
* Create a type-safe AMQP worker from a contract.
|
|
428
464
|
*
|
|
@@ -453,8 +489,10 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
453
489
|
handlers,
|
|
454
490
|
urls,
|
|
455
491
|
connectionOptions,
|
|
492
|
+
defaultConsumerOptions,
|
|
456
493
|
logger,
|
|
457
|
-
telemetry
|
|
494
|
+
telemetry,
|
|
495
|
+
connectTimeoutMs
|
|
458
496
|
}: CreateWorkerOptions<TContract>): Future<Result<TypedAmqpWorker<TContract>, TechnicalError>>;
|
|
459
497
|
/**
|
|
460
498
|
* Close the AMQP channel and connection.
|
|
@@ -474,19 +512,13 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
474
512
|
*/
|
|
475
513
|
close(): Future<Result<void, TechnicalError>>;
|
|
476
514
|
/**
|
|
477
|
-
*
|
|
478
|
-
* Defaults are applied in the contract's defineQueue, so we just return the config.
|
|
479
|
-
*/
|
|
480
|
-
private getRetryConfigForConsumer;
|
|
481
|
-
/**
|
|
482
|
-
* Start consuming messages for all consumers.
|
|
483
|
-
* TypeScript guarantees consumers exist (handlers require matching consumers).
|
|
515
|
+
* Start consuming for every entry in `contract.consumers` and `contract.rpcs`.
|
|
484
516
|
*/
|
|
485
517
|
private consumeAll;
|
|
486
518
|
private waitForConnectionReady;
|
|
487
519
|
/**
|
|
488
|
-
* Start consuming messages for a specific
|
|
489
|
-
*
|
|
520
|
+
* Start consuming messages for a specific handler — either a `consumers`
|
|
521
|
+
* entry (regular event/command consumer) or an `rpcs` entry (RPC server).
|
|
490
522
|
*/
|
|
491
523
|
private consume;
|
|
492
524
|
/**
|
|
@@ -499,81 +531,25 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
499
531
|
*/
|
|
500
532
|
private parseAndValidateMessage;
|
|
501
533
|
/**
|
|
502
|
-
*
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
* Handle error in message processing with retry logic.
|
|
507
|
-
*
|
|
508
|
-
* Flow depends on retry mode:
|
|
509
|
-
*
|
|
510
|
-
* **quorum-native mode:**
|
|
511
|
-
* 1. If NonRetryableError -> send directly to DLQ (no retry)
|
|
512
|
-
* 2. Otherwise -> nack with requeue=true (RabbitMQ handles delivery count)
|
|
513
|
-
*
|
|
514
|
-
* **ttl-backoff mode:**
|
|
515
|
-
* 1. If NonRetryableError -> send directly to DLQ (no retry)
|
|
516
|
-
* 2. If max retries exceeded -> send to DLQ
|
|
517
|
-
* 3. Otherwise -> publish to wait queue with TTL for retry
|
|
518
|
-
*
|
|
519
|
-
* **Legacy mode (no retry config):**
|
|
520
|
-
* 1. nack with requeue=true (immediate requeue)
|
|
521
|
-
*/
|
|
522
|
-
private handleError;
|
|
523
|
-
/**
|
|
524
|
-
* Handle error using quorum queue's native delivery limit feature.
|
|
525
|
-
*
|
|
526
|
-
* Simply requeues the message with nack(requeue=true). RabbitMQ automatically:
|
|
527
|
-
* - Increments x-delivery-count header
|
|
528
|
-
* - Dead-letters the message when count exceeds x-delivery-limit
|
|
534
|
+
* Validate an RPC handler's response and publish it back to the caller's reply
|
|
535
|
+
* queue with the same `correlationId`. Published via the AMQP default exchange
|
|
536
|
+
* with `routingKey = msg.properties.replyTo`, which works for both
|
|
537
|
+
* `amq.rabbitmq.reply-to` and any anonymous queue declared by the caller.
|
|
529
538
|
*
|
|
530
|
-
*
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Handle error using TTL + wait queue pattern for exponential backoff.
|
|
535
|
-
*/
|
|
536
|
-
private handleErrorTtlBackoff;
|
|
537
|
-
/**
|
|
538
|
-
* Calculate retry delay with exponential backoff and optional jitter.
|
|
539
|
+
* Validation errors are surfaced as NonRetryableError (handler returned the
|
|
540
|
+
* wrong shape — retrying the same input will not fix it). Publish errors are
|
|
541
|
+
* surfaced as RetryableError so the worker's existing retry logic applies.
|
|
539
542
|
*/
|
|
540
|
-
private
|
|
543
|
+
private publishRpcResponse;
|
|
541
544
|
/**
|
|
542
|
-
*
|
|
543
|
-
*
|
|
545
|
+
* Process a single consumed message: validate, invoke handler, optionally
|
|
546
|
+
* publish the RPC response, record telemetry, and handle errors.
|
|
544
547
|
*/
|
|
545
|
-
private
|
|
548
|
+
private processMessage;
|
|
546
549
|
/**
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
* ┌─────────────────────────────────────────────────────────────────┐
|
|
550
|
-
* │ Retry Flow (Native RabbitMQ TTL + DLX Pattern) │
|
|
551
|
-
* ├─────────────────────────────────────────────────────────────────┤
|
|
552
|
-
* │ │
|
|
553
|
-
* │ 1. Handler throws any Error │
|
|
554
|
-
* │ ↓ │
|
|
555
|
-
* │ 2. Worker publishes to DLX with routing key: {queue}-wait │
|
|
556
|
-
* │ ↓ │
|
|
557
|
-
* │ 3. DLX routes to wait queue: {queue}-wait │
|
|
558
|
-
* │ (with expiration: calculated backoff delay) │
|
|
559
|
-
* │ ↓ │
|
|
560
|
-
* │ 4. Message waits in queue until TTL expires │
|
|
561
|
-
* │ ↓ │
|
|
562
|
-
* │ 5. Expired message dead-lettered to DLX │
|
|
563
|
-
* │ (with routing key: {queue}) │
|
|
564
|
-
* │ ↓ │
|
|
565
|
-
* │ 6. DLX routes back to main queue → RETRY │
|
|
566
|
-
* │ ↓ │
|
|
567
|
-
* │ 7. If retries exhausted: nack without requeue → DLQ │
|
|
568
|
-
* │ │
|
|
569
|
-
* └─────────────────────────────────────────────────────────────────┘
|
|
550
|
+
* Consume messages one at a time.
|
|
570
551
|
*/
|
|
571
|
-
private
|
|
572
|
-
/**
|
|
573
|
-
* Send message to dead letter queue.
|
|
574
|
-
* Nacks the message without requeue, relying on DLX configuration.
|
|
575
|
-
*/
|
|
576
|
-
private sendToDLQ;
|
|
552
|
+
private consumeSingle;
|
|
577
553
|
}
|
|
578
554
|
//#endregion
|
|
579
555
|
//#region src/handlers.d.ts
|
|
@@ -626,9 +602,7 @@ declare class TypedAmqpWorker<TContract extends ContractDefinition> {
|
|
|
626
602
|
* ```
|
|
627
603
|
*/
|
|
628
604
|
declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>): WorkerInferConsumerHandlerEntry<TContract, TName>;
|
|
629
|
-
declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>, options:
|
|
630
|
-
prefetch?: number;
|
|
631
|
-
}): WorkerInferConsumerHandlerEntry<TContract, TName>;
|
|
605
|
+
declare function defineHandler<TContract extends ContractDefinition, TName extends InferConsumerNames<TContract>>(contract: TContract, consumerName: TName, handler: WorkerInferConsumerHandler<TContract, TName>, options: ConsumerOptions): WorkerInferConsumerHandlerEntry<TContract, TName>;
|
|
632
606
|
/**
|
|
633
607
|
* Define multiple type-safe handlers for consumers in a contract.
|
|
634
608
|
*
|
|
@@ -660,5 +634,5 @@ declare function defineHandler<TContract extends ContractDefinition, TName exten
|
|
|
660
634
|
*/
|
|
661
635
|
declare function defineHandlers<TContract extends ContractDefinition>(contract: TContract, handlers: WorkerInferConsumerHandlers<TContract>): WorkerInferConsumerHandlers<TContract>;
|
|
662
636
|
//#endregion
|
|
663
|
-
export { type CreateWorkerOptions, type HandlerError, MessageValidationError, NonRetryableError, RetryableError, TypedAmqpWorker, type WorkerConsumedMessage, type WorkerInferConsumedMessage, type WorkerInferConsumerHandler, type WorkerInferConsumerHandlerEntry, type WorkerInferConsumerHandlers, type WorkerInferConsumerHeaders, defineHandler, defineHandlers, isHandlerError, isNonRetryableError, isRetryableError, nonRetryable, retryable };
|
|
637
|
+
export { type ConsumerOptions, type CreateWorkerOptions, type HandlerError, MessageValidationError, NonRetryableError, RetryableError, TypedAmqpWorker, type WorkerConsumedMessage, type WorkerInferConsumedMessage, type WorkerInferConsumerHandler, type WorkerInferConsumerHandlerEntry, type WorkerInferConsumerHandlers, type WorkerInferConsumerHeaders, defineHandler, defineHandlers, isHandlerError, isNonRetryableError, isRetryableError, nonRetryable, retryable };
|
|
664
638
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":["amqp","EventEmitter","TcpSocketConnectOpts","ConnectionOptions","ChannelWrapper","CreateChannelOpts","ConnectionUrl","Options","Connect","AmqpConnectionOptions","url","connectionOptions","ConnectListener","Connection","connection","arg","ConnectFailedListener","Error","err","Buffer","noDelay","timeout","keepAlive","keepAliveDelay","clientProperties","credentials","mechanism","username","password","response","AmqpConnectionManagerOptions","Promise","heartbeatIntervalInSeconds","reconnectTimeInSeconds","findServers","urls","callback","IAmqpConnectionManager","Function","ChannelModel","addListener","event","args","listener","reason","listeners","eventName","on","once","prependListener","prependOnceListener","removeListener","connect","options","reconnect","createChannel","close","isConnected","channelCount","AmqpConnectionManager","_channels","_currentUrl","_closed","_cancelRetriesHandler","_connectPromise","_currentConnection","_findServers","_urls","constructor","_connect","default"],"sources":["../../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@0.
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":["amqp","EventEmitter","TcpSocketConnectOpts","ConnectionOptions","ChannelWrapper","CreateChannelOpts","ConnectionUrl","Options","Connect","AmqpConnectionOptions","url","connectionOptions","ConnectListener","Connection","connection","arg","ConnectFailedListener","Error","err","Buffer","noDelay","timeout","keepAlive","keepAliveDelay","clientProperties","credentials","mechanism","username","password","response","AmqpConnectionManagerOptions","Promise","heartbeatIntervalInSeconds","reconnectTimeInSeconds","findServers","urls","callback","IAmqpConnectionManager","Function","ChannelModel","addListener","event","args","listener","reason","listeners","eventName","on","once","prependListener","prependOnceListener","removeListener","connect","options","reconnect","createChannel","close","isConnected","channelCount","AmqpConnectionManager","_channels","_currentUrl","_closed","_cancelRetriesHandler","_connectPromise","_currentConnection","_findServers","_urls","constructor","_connect","default"],"sources":["../../../node_modules/.pnpm/amqp-connection-manager@5.0.0_amqplib@1.0.3/node_modules/amqp-connection-manager/dist/types/AmqpConnectionManager.d.ts","../src/errors.ts","../src/types.ts","../src/worker.ts","../src/handlers.ts"],"x_google_ignoreList":[0],"mappings":"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"}
|