@spinajs/queue-amqp-transport 2.0.482 → 2.0.485

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=connection-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-factory.d.ts","sourceRoot":"","sources":["../../src/connection-factory.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const di_1 = require("@spinajs/di");
4
+ const connection_js_1 = require("./connection.js");
5
+ const configuration_1 = require("@spinajs/configuration");
6
+ /**
7
+ * Create factory func that sets client-id to connection by app name.
8
+ * We cannot have two connections with the same ID, so by default we take app-name
9
+ * with NODE_ENV and then name from options.
10
+ *
11
+ * This way we can share the same config/connections across multiple apps.
12
+ */
13
+ di_1.DI.register(async (container, options) => {
14
+ const cfg = container.get(configuration_1.Configuration);
15
+ const appName = cfg.get('app.name', 'no-app');
16
+ const env = cfg.get('process.env.APP_ENV', 'development');
17
+ const c = new connection_js_1.AmqpQueueClient({
18
+ ...options,
19
+ clientId: `${appName}-${env}-${options.name}`,
20
+ });
21
+ await c.resolve();
22
+ return c;
23
+ }).as(connection_js_1.AmqpQueueClient);
24
+ //# sourceMappingURL=connection-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-factory.js","sourceRoot":"","sources":["../../src/connection-factory.ts"],"names":[],"mappings":";;AAAA,oCAAiC;AAEjC,mDAAkD;AAClD,0DAAuD;AAEvD;;;;;;GAMG;AACH,OAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,OAAgC,EAAE,EAAE;IAChE,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,6BAAa,CAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAS,UAAU,EAAE,QAAQ,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAS,qBAAqB,EAAE,aAAa,CAAC,CAAC;IAElE,MAAM,CAAC,GAAG,IAAI,+BAAe,CAAC;QAC5B,GAAG,OAAO;QACV,QAAQ,EAAE,GAAG,OAAO,IAAI,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE;KAC9C,CAAC,CAAC;IACH,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC,CAAC;AACX,CAAC,CAAC,CAAC,EAAE,CAAC,+BAAe,CAAC,CAAC"}
@@ -0,0 +1,148 @@
1
+ import { IQueueMessage, IQueueConnectionOptions, QueueClient, QueueMessage } from '@spinajs/queue';
2
+ import { Channel, ChannelModel, ConfirmChannel, ConsumeMessage, Options } from 'amqplib';
3
+ import { Constructor } from '@spinajs/di';
4
+ import { ResiliencePipeline } from '@spinajs/util';
5
+ /**
6
+ * Everything needed to re-establish a subscription after a reconnect. amqplib consumers do not
7
+ * survive a dropped connection, so we keep descriptors and replay them on every (re)connect.
8
+ */
9
+ interface ISubscriptionDescriptor {
10
+ channel: string;
11
+ callback: (e: IQueueMessage) => Promise<void>;
12
+ subscriptionId?: string;
13
+ durable: boolean;
14
+ /** Runtime state - refreshed on every (re)connect. */
15
+ consumerTag?: string;
16
+ queue?: string;
17
+ }
18
+ interface IPendingEmit {
19
+ message: IQueueMessage;
20
+ resolve: () => void;
21
+ reject: (err: unknown) => void;
22
+ }
23
+ export declare class AmqpQueueClient extends QueueClient {
24
+ protected Connection: ChannelModel;
25
+ /** Confirm channel used for publishing so emit() resolves only after a broker ack. */
26
+ protected PublishChannel: ConfirmChannel;
27
+ /** Separate channel for consumers so publisher back-pressure cannot stall consumer acks. */
28
+ protected ConsumeChannel: Channel;
29
+ protected Subscriptions: Map<string, ISubscriptionDescriptor>;
30
+ protected AssertedQueues: Set<string>;
31
+ protected AssertedExchanges: Set<string>;
32
+ protected AssertedRetryQueues: Set<string>;
33
+ /** Messages emitted while disconnected - flushed on (re)connect. */
34
+ protected PendingEmits: IPendingEmit[];
35
+ protected Connected: boolean;
36
+ protected Disposing: boolean;
37
+ protected ReconnectTimer?: ReturnType<typeof setTimeout>;
38
+ /** Publisher-side resilience: time-bound + retry each publish so transient broker hiccups
39
+ * don't lose an emit. Safe against the resulting duplicates because consumers dedupe by JobId. */
40
+ protected EmitPipeline: ResiliencePipeline<void>;
41
+ get ClientId(): string;
42
+ protected get TopicPrefix(): string;
43
+ protected get ReconnectDelay(): number;
44
+ protected get Prefetch(): number;
45
+ get IsConnected(): boolean;
46
+ constructor(options: IQueueConnectionOptions);
47
+ resolve(): Promise<void>;
48
+ /**
49
+ * Creates the underlying amqplib connection. Isolated as a seam so tests can inject a fake
50
+ * broker without a real server ( mirrors the STOMP transport's createClient seam ).
51
+ */
52
+ protected createConnection(url: string | Options.Connect, socketOptions: Record<string, unknown>): Promise<ChannelModel>;
53
+ /**
54
+ * Builds the amqplib connection target from the configured options.
55
+ *
56
+ * A url-style host ( `amqp://.../vhost` ) is parsed into an explicit {@link Options.Connect}
57
+ * object rather than passed as a raw string, so every setting - crucially the credentials - is a
58
+ * clear field instead of being buried in the url. amqplib derives credentials for a *string* url
59
+ * only from the url's own userinfo, which is why the discrete `login` / `password` config fields
60
+ * were previously ignored for a url host. Credentials embedded in the url still win; the config
61
+ * fields are the fallback when the url carries none ( matching amqplib's own precedence ).
62
+ */
63
+ protected buildConnectionTarget(): Options.Connect;
64
+ /** Connect-options object built from the discrete `host` / `port` / `login` / `password` fields. */
65
+ protected connectOptionsFromFields(hostname: string): Options.Connect;
66
+ dispose(): Promise<void>;
67
+ /**
68
+ * Establishes the connection + channels, then replays subscriptions and flushes buffered emits.
69
+ * Called on initial resolve and on every reconnect.
70
+ */
71
+ protected connect(): Promise<void>;
72
+ /**
73
+ * Handles an unexpected connection drop by scheduling a reconnect ( unless we are disposing ).
74
+ */
75
+ protected onConnectionLost(): void;
76
+ protected scheduleReconnect(): void;
77
+ emit(message: IQueueMessage): Promise<void>;
78
+ subscribe(channelOrMessage: string | Constructor<QueueMessage>, callback: (e: IQueueMessage) => Promise<void>, subscriptionId?: string, durable?: boolean): Promise<void>;
79
+ unsubscribe(channelOrMessage: string | Constructor<QueueMessage>, _removeDurable?: boolean): void;
80
+ /**
81
+ * Re-establishes every known subscription. Called after a (re)connect.
82
+ */
83
+ protected replaySubscriptions(): Promise<void>;
84
+ /**
85
+ * Declares the queue for a subscription and starts consuming, wiring ack/nack + retry/dead-letter.
86
+ */
87
+ protected startConsumer(descriptor: ISubscriptionDescriptor): Promise<void>;
88
+ /**
89
+ * Handles a message whose consumer callback rejected.
90
+ *
91
+ * Events are fire-and-forget - logged and acked ( dropped ). Jobs are retried up to their
92
+ * RetryCount by re-publishing to a TTL "retry" queue that dead-letters back to the work queue
93
+ * after an exponential delay, then dead-lettered once retries are exhausted.
94
+ */
95
+ protected handleFailedMessage(msg: ConsumeMessage, qMessage: IQueueMessage, channel: string, err: unknown): void;
96
+ /**
97
+ * Republishes a failed job to a per-delay TTL retry queue that dead-letters back to the work
98
+ * queue after the delay, giving broker-side ( crash-safe ) exponential backoff. Then acks original.
99
+ */
100
+ protected retryJob(msg: ConsumeMessage, qMessage: IQueueMessage, workQueue: string, nextAttempt: number, reason: string): Promise<void>;
101
+ /**
102
+ * Publishes a failed/unparseable message to the dead-letter queue and acks the original to
103
+ * unblock the source queue. When no dead-letter queue is configured the message is dropped
104
+ * ( acked ) with a warning - we never nack-loop a poison message forever.
105
+ */
106
+ protected deadLetterRaw(msg: ConsumeMessage, dlq: string | undefined, channel: string, reason: string, attempt?: number): void;
107
+ /**
108
+ * Exponential backoff ( ms ) for the given retry attempt, based on `Options.retryDelay`.
109
+ * Returns 0 ( immediate redelivery ) when no base delay is configured.
110
+ */
111
+ protected retryBackoff(attempt: number): number;
112
+ /**
113
+ * Publisher-side resilience pipeline: bounds each publish by a timeout and retries transient
114
+ * failures / nacks with exponential backoff. Consumer dedup ( by JobId ) makes the resulting
115
+ * rare duplicates harmless.
116
+ */
117
+ protected buildEmitPipeline(): ResiliencePipeline<void>;
118
+ protected publishMessage(message: IQueueMessage): Promise<void>;
119
+ /** Asserts the destination ( once ) and publishes a single message on the confirm channel. */
120
+ protected publishToChannel(channel: string, buffer: Buffer, options: Options.Publish): Promise<void>;
121
+ /**
122
+ * Publishes on the confirm channel and resolves only once the broker acks the message.
123
+ */
124
+ protected publishWithConfirm(exchange: string, routingKey: string, content: Buffer, options: Options.Publish): Promise<void>;
125
+ protected flushPendingEmits(): Promise<void>;
126
+ /**
127
+ * Declares ( and for topics binds ) the broker queue a subscription should consume from.
128
+ */
129
+ protected assertSubscriptionQueue(channel: string, subscriptionId?: string, durable?: boolean): Promise<string>;
130
+ /**
131
+ * Declares a durable work queue, asserting it on the broker only once per connection.
132
+ */
133
+ protected assertQueue(channel: Channel | ConfirmChannel, name: string): Promise<string>;
134
+ /**
135
+ * Declares a durable fanout exchange, asserting it on the broker only once per connection.
136
+ */
137
+ protected assertExchange(channel: Channel | ConfirmChannel, name: string): Promise<void>;
138
+ /**
139
+ * Declares a durable TTL retry queue that dead-letters expired messages back to `workQueue`
140
+ * ( via the default exchange, routing key = queue name ). One queue per distinct delay.
141
+ */
142
+ protected assertRetryQueue(workQueue: string, delay: number): Promise<string>;
143
+ protected isTopic(channel: string): boolean;
144
+ protected closeChannel(channel?: Channel | ConfirmChannel): Promise<void>;
145
+ protected warnOnUnsupportedScheduling(message: IQueueMessage): void;
146
+ }
147
+ export {};
148
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection.ts"],"names":[],"mappings":"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"}