@autofleet/rabbit 5.0.28 → 5.1.0-alpha.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 +469 -3
- package/dist/{index-Di_b_UEl.d.ts → index-CBlhQYQ_.d.cts} +26 -75
- package/dist/{index-BSNGP44W.d.cts → index-CdC0BR3j.d.ts} +26 -75
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mock/index.d.cts +1 -1
- package/dist/mock/index.d.ts +1 -1
- package/dist/mock/vitest.cjs +1 -1
- package/dist/mock/vitest.cjs.map +1 -1
- package/dist/mock/vitest.d.cts +1 -2
- package/dist/mock/vitest.d.ts +1 -2
- package/dist/mock/vitest.js +1 -1
- package/dist/mock/vitest.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,8 +1,474 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @autofleet/rabbit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
RabbitMQ wrapper for Autofleet microservices with support for both classic and quorum queues.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Dual Queue Support**: Classic and quorum queues with automatic vhost separation
|
|
8
|
+
- **Connection Pooling**: Efficient vhost-based connection management
|
|
9
|
+
- **Graceful Shutdown**: Proper cleanup of consumers and connections
|
|
10
|
+
- **Redis Integration**: Message locking and timestamp validation
|
|
11
|
+
- **Tracing Support**: Integration with @autofleet/zehut for distributed tracing
|
|
12
|
+
- **TypeScript**: Full type safety with TypeScript definitions
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @autofleet/rabbit
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import RabbitMq from '@autofleet/rabbit';
|
|
24
|
+
|
|
25
|
+
// Initialize with optional Redis config
|
|
26
|
+
const rabbit = new RabbitMq({
|
|
27
|
+
rabbitHost: 'localhost:5672',
|
|
28
|
+
logger: yourLogger,
|
|
29
|
+
}, redisConfig);
|
|
30
|
+
|
|
31
|
+
// Configure which queues should use quorum type
|
|
32
|
+
process.env.QUORUM_QUEUES = 'order-events,user-updates,notifications';
|
|
33
|
+
|
|
34
|
+
// Send to queue (automatically routes to correct vhost)
|
|
35
|
+
await rabbit.sendToQueue('order-events', { orderId: 123 });
|
|
36
|
+
|
|
37
|
+
// Consume from queue
|
|
38
|
+
await rabbit.consume('order-events', async (msg, ack, nack) => {
|
|
39
|
+
console.log('Received:', msg.content);
|
|
40
|
+
await ack();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Publish to exchange
|
|
44
|
+
await rabbit.publish('events', { type: 'order.created' });
|
|
45
|
+
|
|
46
|
+
// Consume from exchange
|
|
47
|
+
await rabbit.consumeFromExchange('order-queue', 'events', async (msg, ack, nack) => {
|
|
48
|
+
console.log('Received:', msg.content);
|
|
49
|
+
await ack();
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
### Environment Variables
|
|
56
|
+
|
|
57
|
+
- **`QUORUM_QUEUES`**: Comma-separated list of queue names that should use quorum type
|
|
58
|
+
```bash
|
|
59
|
+
QUORUM_QUEUES="order-events,user-updates,notifications"
|
|
60
|
+
```
|
|
61
|
+
- Queues in this list will be created in the `quorum-vhost` vhost with `x-queue-type: quorum`
|
|
62
|
+
- All other queues will use the default vhost with `x-queue-type: classic`
|
|
63
|
+
|
|
64
|
+
- **`RABBITMQ_USERNAME`**: RabbitMQ username (default: `guest`)
|
|
65
|
+
- **`RABBITMQ_PASSWORD`**: RabbitMQ password (default: `guest`)
|
|
66
|
+
- **`RABBITMQ_SERVICE_HOST`**: RabbitMQ host (default: `localhost`)
|
|
67
|
+
|
|
68
|
+
### Constructor Options
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
interface AfRabbitOptions {
|
|
72
|
+
rabbitHost?: string; // RabbitMQ host:port
|
|
73
|
+
vhost?: string; // Default vhost name (default: 'quorum-vhost')
|
|
74
|
+
logger?: LoggerInstanceManager; // Custom logger instance
|
|
75
|
+
disableReconnect?: boolean; // Disable automatic reconnection
|
|
76
|
+
dontGracefulShutdown?: boolean; // Disable graceful shutdown handlers
|
|
77
|
+
dontRetryAssert?: boolean; // Don't retry on queue assertion errors
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API Reference
|
|
82
|
+
|
|
83
|
+
### Publishing
|
|
84
|
+
|
|
85
|
+
#### `sendToQueue(queue: string, content: any, options?: Options.AssertQueue, customHeaders?: PublishOptions['headers'])`
|
|
86
|
+
|
|
87
|
+
Send a message to a specific queue. The queue type (classic/quorum) is determined automatically based on the queue name.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
await rabbit.sendToQueue('order-events', { orderId: 123 }, {
|
|
91
|
+
durable: true,
|
|
92
|
+
messageTtl: 60000,
|
|
93
|
+
}, {
|
|
94
|
+
customHeader: 'value',
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### `publish(exchange: string, content: any, customHeaders?: PublishOptions['headers'])`
|
|
99
|
+
|
|
100
|
+
Publish a message to an exchange.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
await rabbit.publish('events', { type: 'order.created' });
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Consuming
|
|
107
|
+
|
|
108
|
+
#### `consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions)`
|
|
109
|
+
|
|
110
|
+
Consume messages from a queue.
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
await rabbit.consume('order-events', async (msg, ack, nack) => {
|
|
114
|
+
try {
|
|
115
|
+
await processOrder(msg.content);
|
|
116
|
+
await ack(); // Acknowledge message
|
|
117
|
+
} catch (error) {
|
|
118
|
+
await nack(msg, { skipRetry: false }); // Retry the message
|
|
119
|
+
}
|
|
120
|
+
}, {
|
|
121
|
+
retries: 3,
|
|
122
|
+
deadMessageTtl: 86400000, // 24 hours
|
|
123
|
+
limit: 10, // Prefetch limit
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
##### Consume Options
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
interface ConsumeOptions {
|
|
131
|
+
retries?: number; // Number of retries before sending to dead queue
|
|
132
|
+
deadMessageTtl?: number; // TTL for dead queue messages (ms)
|
|
133
|
+
messageTtl?: number; // TTL for messages (ms)
|
|
134
|
+
limit?: number; // Prefetch limit
|
|
135
|
+
lockTimeout?: number; // Redis lock timeout (ms)
|
|
136
|
+
useConsumeWithLock?: boolean; // Enable Redis-based locking
|
|
137
|
+
auditContext?: any; // Audit context function
|
|
138
|
+
enableRabbitTrace?: boolean; // Enable tracing integration
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### `consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions)`
|
|
143
|
+
|
|
144
|
+
Consume messages from an exchange by binding a queue to it.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
await rabbit.consumeFromExchange('order-queue', 'events', async (msg, ack, nack) => {
|
|
148
|
+
console.log('Event:', msg.content);
|
|
149
|
+
await ack();
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Queue Management
|
|
154
|
+
|
|
155
|
+
#### `assertQueue(queueName: string, options?: Options.AssertQueue)`
|
|
156
|
+
|
|
157
|
+
Assert a queue exists, creating it if necessary. Queue type is determined automatically.
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
await rabbit.assertQueue('order-events', {
|
|
161
|
+
durable: true,
|
|
162
|
+
arguments: {
|
|
163
|
+
'x-message-ttl': 60000,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### `assertExchange(exchangeName: string, vhost?: string)`
|
|
169
|
+
|
|
170
|
+
Assert an exchange exists, creating it if necessary.
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
await rabbit.assertExchange('events');
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### `bindQueue(queue: string, exchange: string)`
|
|
177
|
+
|
|
178
|
+
Bind a queue to an exchange.
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
await rabbit.bindQueue('order-queue', 'events');
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### `getQueueLength(queue: string)`
|
|
185
|
+
|
|
186
|
+
Get the number of messages in a queue.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
const { messageCount } = await rabbit.getQueueLength('order-events');
|
|
190
|
+
console.log(`Queue has ${messageCount} messages`);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Connection Management
|
|
194
|
+
|
|
195
|
+
#### `isConnected()`
|
|
196
|
+
|
|
197
|
+
Check if all connections are healthy and all consumers are registered.
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
const healthy = await rabbit.isConnected();
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### `gracefulShutdown(signal: string)`
|
|
204
|
+
|
|
205
|
+
Gracefully shutdown all connections and consumers. This is automatically called on `SIGTERM` and `SIGINT` unless `dontGracefulShutdown` is set.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
await rabbit.gracefulShutdown('SIGTERM');
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Architecture
|
|
212
|
+
|
|
213
|
+
### Queue Type Determination
|
|
214
|
+
|
|
215
|
+
Queues are automatically routed to the appropriate vhost based on the `QUORUM_QUEUES` environment variable:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// Environment
|
|
219
|
+
QUORUM_QUEUES="order-events,user-updates"
|
|
220
|
+
|
|
221
|
+
// Routing
|
|
222
|
+
sendToQueue('order-events', data) → quorum-vhost (quorum queue)
|
|
223
|
+
sendToQueue('other-queue', data) → default vhost (classic queue)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Connection Pooling
|
|
227
|
+
|
|
228
|
+
The package maintains separate connection pools for each vhost:
|
|
229
|
+
|
|
230
|
+
- **Publish connections**: One connection per vhost for publishing
|
|
231
|
+
- **Consume connections**: One connection per vhost for consuming
|
|
232
|
+
- **Channels**: One channel per vhost for publishing
|
|
233
|
+
|
|
234
|
+
This architecture ensures efficient connection reuse while maintaining proper isolation between queue types.
|
|
235
|
+
|
|
236
|
+
### Message Headers
|
|
237
|
+
|
|
238
|
+
All published messages automatically include the following headers:
|
|
239
|
+
|
|
240
|
+
- `creationTimestamp`: Unix timestamp in milliseconds
|
|
241
|
+
- `x-user-id`: User ID from zehut context (if available)
|
|
242
|
+
- `x-contexts-ids`: User context IDs from zehut (if available)
|
|
243
|
+
- `x-tracing-id`: Trace ID from zehut context (if available)
|
|
244
|
+
|
|
245
|
+
### Dead Letter Queues
|
|
246
|
+
|
|
247
|
+
When a message exceeds the retry limit, it's automatically sent to a dead letter queue:
|
|
248
|
+
|
|
249
|
+
- **Queue name**: `{original-queue}-dead`
|
|
250
|
+
- **TTL**: Configurable via `deadMessageTtl` option (default: from `messageTtl`)
|
|
251
|
+
|
|
252
|
+
## Migration Guides
|
|
253
|
+
|
|
254
|
+
### V6 Migration (Quorum Queue Refactoring)
|
|
255
|
+
|
|
256
|
+
**Version 6.0.0** introduces a cleaner architecture for managing classic and quorum queues with **breaking changes**.
|
|
257
|
+
|
|
258
|
+
#### Breaking Changes
|
|
259
|
+
|
|
260
|
+
1. **Removed parameters**:
|
|
261
|
+
```typescript
|
|
262
|
+
// ❌ Old (deprecated)
|
|
263
|
+
await rabbit.sendToQueue(queue, data, options, headers, true); // isQuorumQueue param
|
|
264
|
+
await rabbit.publish(exchange, data, headers, true); // isQuorumQueue param
|
|
265
|
+
|
|
266
|
+
// ✅ New
|
|
267
|
+
await rabbit.sendToQueue(queue, data, options, headers);
|
|
268
|
+
await rabbit.publish(exchange, data, headers);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
2. **Removed methods**:
|
|
272
|
+
- `assertChannel()` - Use `assertChannelForVhost(vhost)` instead (internal use only)
|
|
273
|
+
|
|
274
|
+
3. **Updated method signatures**:
|
|
275
|
+
```typescript
|
|
276
|
+
// ❌ Old
|
|
277
|
+
await rabbit.assertExchange(exchange, connectionData);
|
|
278
|
+
|
|
279
|
+
// ✅ New
|
|
280
|
+
await rabbit.assertExchange(exchange); // vhost optional, defaults to ''
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
4. **Removed environment variables**:
|
|
284
|
+
- `DISABLE_QUORUM_QUEUES_CONSUME` - No longer needed
|
|
285
|
+
- `DISABLE_QUORUM_QUEUES_PUBLISH` - No longer needed
|
|
286
|
+
|
|
287
|
+
5. **Removed type options**:
|
|
288
|
+
```typescript
|
|
289
|
+
// ❌ Old (deprecated)
|
|
290
|
+
interface ConsumeOptions {
|
|
291
|
+
isQuorumQueue?: boolean; // REMOVED
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### Migration Steps
|
|
296
|
+
|
|
297
|
+
**Step 1**: Update your code to remove `isQuorumQueue` parameters
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// Before
|
|
301
|
+
await rabbit.sendToQueue('orders', data, options, headers, true);
|
|
302
|
+
|
|
303
|
+
// After
|
|
304
|
+
await rabbit.sendToQueue('orders', data, options, headers);
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Step 2**: Configure `QUORUM_QUEUES` environment variable
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
# Add to your environment
|
|
311
|
+
QUORUM_QUEUES="orders,events,notifications"
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Step 3**: Remove old environment variables
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
# Remove these from your environment
|
|
318
|
+
# DISABLE_QUORUM_QUEUES_CONSUME
|
|
319
|
+
# DISABLE_QUORUM_QUEUES_PUBLISH
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Step 4**: Update `assertExchange` calls
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
// Before
|
|
326
|
+
await rabbit.assertExchange(exchange, connectionData);
|
|
327
|
+
|
|
328
|
+
// After
|
|
329
|
+
await rabbit.assertExchange(exchange);
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### Gradual Migration Strategy
|
|
333
|
+
|
|
334
|
+
For safe migration across multiple services:
|
|
335
|
+
|
|
336
|
+
1. **Deploy with empty `QUORUM_QUEUES`** initially (all queues remain classic):
|
|
337
|
+
```bash
|
|
338
|
+
QUORUM_QUEUES=""
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
2. **Gradually add queues** to the list:
|
|
342
|
+
```bash
|
|
343
|
+
QUORUM_QUEUES="order-events" # Start with one
|
|
344
|
+
# Monitor and verify
|
|
345
|
+
QUORUM_QUEUES="order-events,user-updates" # Add more
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
3. **Remove old parameters** from code (cleanup):
|
|
349
|
+
```typescript
|
|
350
|
+
// Remove isQuorumQueue parameters
|
|
351
|
+
await rabbit.sendToQueue(queue, data, options, headers);
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
#### Benefits of V6
|
|
355
|
+
|
|
356
|
+
- **40% less code**: Removed ~600 lines of duplicate infrastructure
|
|
357
|
+
- **Better maintainability**: Single code path for all queue types
|
|
358
|
+
- **Clearer configuration**: Queue type determined by name, not global flags
|
|
359
|
+
- **Improved performance**: Connection pooling reduces memory overhead
|
|
360
|
+
- **Easier testing**: Simpler architecture with fewer edge cases
|
|
361
|
+
|
|
362
|
+
### V5 Migration
|
|
363
|
+
|
|
364
|
+
The breaking change in version 5 is the removal of `zehut` from dependencies and usage as a peer-dependency.
|
|
4
365
|
The required version of zehut is now `^4.0.0`.
|
|
5
366
|
|
|
6
367
|
This was moved to being a peer-dependency in order to ensure that the version of `zehut` used here is the same as used in the MS, and not risk the package using v4 while the service is using v3, which would cause `zehut` to have multiple traces, which will not all hold the correct data.
|
|
7
368
|
|
|
8
|
-
Additionally, the minimum node version is now 18, due to the minimum version of node defined in `zehut`.
|
|
369
|
+
Additionally, the minimum node version is now 18, due to the minimum version of node defined in `zehut`.
|
|
370
|
+
|
|
371
|
+
## Examples
|
|
372
|
+
|
|
373
|
+
### Basic Producer-Consumer
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
import RabbitMq from '@autofleet/rabbit';
|
|
377
|
+
|
|
378
|
+
const rabbit = new RabbitMq();
|
|
379
|
+
|
|
380
|
+
// Set up quorum queues
|
|
381
|
+
process.env.QUORUM_QUEUES = 'important-events';
|
|
382
|
+
|
|
383
|
+
// Producer
|
|
384
|
+
async function sendEvent(event: any) {
|
|
385
|
+
await rabbit.sendToQueue('important-events', event);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Consumer
|
|
389
|
+
async function startConsumer() {
|
|
390
|
+
await rabbit.consume('important-events', async (msg, ack, nack) => {
|
|
391
|
+
try {
|
|
392
|
+
console.log('Processing event:', msg.content);
|
|
393
|
+
await processEvent(msg.content);
|
|
394
|
+
await ack();
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error('Failed to process event:', error);
|
|
397
|
+
await nack(msg); // Will retry based on options
|
|
398
|
+
}
|
|
399
|
+
}, {
|
|
400
|
+
retries: 3,
|
|
401
|
+
limit: 10,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
startConsumer();
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Fan-out Pattern with Exchange
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
import RabbitMq from '@autofleet/rabbit';
|
|
412
|
+
|
|
413
|
+
const rabbit = new RabbitMq();
|
|
414
|
+
|
|
415
|
+
// Set up exchange and queues
|
|
416
|
+
await rabbit.assertExchange('notifications');
|
|
417
|
+
await rabbit.assertQueue('email-notifications');
|
|
418
|
+
await rabbit.assertQueue('sms-notifications');
|
|
419
|
+
await rabbit.bindQueue('email-notifications', 'notifications');
|
|
420
|
+
await rabbit.bindQueue('sms-notifications', 'notifications');
|
|
421
|
+
|
|
422
|
+
// Publisher
|
|
423
|
+
await rabbit.publish('notifications', {
|
|
424
|
+
type: 'order.created',
|
|
425
|
+
orderId: 123,
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Email consumer
|
|
429
|
+
await rabbit.consumeFromExchange('email-notifications', 'notifications',
|
|
430
|
+
async (msg, ack, nack) => {
|
|
431
|
+
await sendEmail(msg.content);
|
|
432
|
+
await ack();
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
// SMS consumer
|
|
437
|
+
await rabbit.consumeFromExchange('sms-notifications', 'notifications',
|
|
438
|
+
async (msg, ack, nack) => {
|
|
439
|
+
await sendSMS(msg.content);
|
|
440
|
+
await ack();
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### With Redis Locking
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
import RabbitMq from '@autofleet/rabbit';
|
|
449
|
+
|
|
450
|
+
const rabbit = new RabbitMq(undefined, {
|
|
451
|
+
host: 'localhost',
|
|
452
|
+
port: 6379,
|
|
453
|
+
prefix: 'myapp:',
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
await rabbit.consume('order-processing', async (msg, ack, nack) => {
|
|
457
|
+
// Redis lock is automatically acquired before this callback
|
|
458
|
+
// and released after ack/nack
|
|
459
|
+
|
|
460
|
+
await processOrder(msg.content);
|
|
461
|
+
await ack(); // Lock is released here
|
|
462
|
+
}, {
|
|
463
|
+
useConsumeWithLock: true,
|
|
464
|
+
lockTimeout: 30000, // 30 seconds
|
|
465
|
+
});
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## License
|
|
469
|
+
|
|
470
|
+
ISC
|
|
471
|
+
|
|
472
|
+
## Contributing
|
|
473
|
+
|
|
474
|
+
Please report issues at: https://github.com/autofleet/autorepo
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { EventEmitter } from "node:events";
|
|
2
1
|
import RedisLock from "redis-lock";
|
|
3
2
|
import { AmqpConnectionManager, ChannelWrapper, CreateChannelOpts } from "amqp-connection-manager";
|
|
4
|
-
import { LoggerInstanceManager } from "@autofleet/logger";
|
|
5
|
-
import { createClient } from "redis";
|
|
6
3
|
import { PublishOptions } from "amqp-connection-manager/dist/types/ChannelWrapper";
|
|
7
4
|
import { ConfirmChannel, ConsumeMessage, Options, Replies } from "amqplib";
|
|
5
|
+
import { LoggerInstanceManager } from "@autofleet/logger";
|
|
6
|
+
import { createClient } from "redis";
|
|
8
7
|
|
|
9
8
|
//#region src/lib/redis.d.ts
|
|
10
9
|
interface RedisConfig {
|
|
@@ -15,10 +14,6 @@ interface RedisConfig {
|
|
|
15
14
|
declare const getRedisInstance: (config: RedisConfig) => ReturnType<typeof createClient>;
|
|
16
15
|
//#endregion
|
|
17
16
|
//#region src/lib/types.d.ts
|
|
18
|
-
type ExchangesCache = Record<string, Replies.AssertExchange | undefined>;
|
|
19
|
-
type QueuesCache = Record<string, Replies.AssertQueue | undefined>;
|
|
20
|
-
type QueueSetupPromisesDictionary = Record<string, Promise<Replies.AssertQueue> | undefined>;
|
|
21
|
-
type AssertExchangePromisesDictionary = Record<string, Promise<Replies.AssertExchange> | undefined>;
|
|
22
17
|
interface CustomMessageHeaders {
|
|
23
18
|
redisTimestampValidationKey?: string;
|
|
24
19
|
}
|
|
@@ -32,7 +27,6 @@ interface ConsumeOptions {
|
|
|
32
27
|
useConsumeWithLock?: boolean;
|
|
33
28
|
auditContext?: any;
|
|
34
29
|
enableRabbitTrace?: boolean;
|
|
35
|
-
isQuorumQueue?: boolean;
|
|
36
30
|
}
|
|
37
31
|
interface NackOptions {
|
|
38
32
|
skipRetry?: boolean;
|
|
@@ -64,8 +58,7 @@ declare function sendCeleryTaskViaHttp(data: TaskData, {
|
|
|
64
58
|
interface IAfRabbitMq {
|
|
65
59
|
ack(channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null): (userMsg: ConsumeMessage) => Promise<void>;
|
|
66
60
|
nack(channel: ConfirmChannel, queue: string, options: ConsumeOptions, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock?: () => Promise<void>): (userMsg: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>;
|
|
67
|
-
|
|
68
|
-
assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>;
|
|
61
|
+
assertExchange(exchangeName: string, vhost?: string): Promise<Replies.AssertExchange>;
|
|
69
62
|
assertQueue(queueName: string, options?: Options.AssertQueue | null): Promise<Replies.AssertQueue>;
|
|
70
63
|
consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
71
64
|
consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
@@ -95,11 +88,6 @@ interface newChannelOpts {
|
|
|
95
88
|
options?: CreateChannelOpts | undefined;
|
|
96
89
|
connection: ConnectionData;
|
|
97
90
|
}
|
|
98
|
-
interface assertChannelOpts {
|
|
99
|
-
channelName?: string;
|
|
100
|
-
force?: boolean;
|
|
101
|
-
connection: ConnectionData;
|
|
102
|
-
}
|
|
103
91
|
declare class RabbitMq implements IAfRabbitMq {
|
|
104
92
|
#private;
|
|
105
93
|
readonly options: AfRabbitOptions;
|
|
@@ -109,98 +97,61 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
109
97
|
static getPublishOptions(customHeaders?: CustomMessageHeaders): PublishOptions;
|
|
110
98
|
readonly DISCONNECT_MSG = "rabbit: connection disconnect";
|
|
111
99
|
readonly RECONNECT_MSG = "rabbit: connection disconnect - reconnecting";
|
|
112
|
-
publishChannel: ChannelWrapper | null;
|
|
113
|
-
publishChannelSetupPromise: Promise<ChannelWrapper> | null;
|
|
114
|
-
readonly publishConnection: ConnectionData;
|
|
115
|
-
readonly consumeConnection: ConnectionData;
|
|
116
|
-
readonly em: EventEmitter;
|
|
117
|
-
readonly exchanges: ExchangesCache;
|
|
118
|
-
readonly queues: QueuesCache;
|
|
119
|
-
readonly queueSetupPromises: QueueSetupPromisesDictionary;
|
|
120
|
-
readonly assertExchangePromises: AssertExchangePromisesDictionary;
|
|
121
100
|
readonly redisClient?: ReturnType<typeof getRedisInstance>;
|
|
122
101
|
readonly redisLock?: ReturnType<typeof RedisLock>;
|
|
123
|
-
|
|
124
|
-
readonly consumersTags: Map<string, {
|
|
125
|
-
channel: ConfirmChannel;
|
|
126
|
-
consumerTag: string;
|
|
127
|
-
}>;
|
|
128
|
-
private readonly consumersToRegister;
|
|
102
|
+
private readonly em;
|
|
129
103
|
private doesVHostExist;
|
|
130
104
|
private readonly vhost;
|
|
131
105
|
private gracefulShutdownStarted;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
readonly
|
|
135
|
-
readonly
|
|
136
|
-
readonly
|
|
137
|
-
readonly
|
|
138
|
-
readonly
|
|
139
|
-
readonly
|
|
140
|
-
readonly
|
|
141
|
-
readonly
|
|
142
|
-
|
|
143
|
-
consumerTag: string;
|
|
144
|
-
}>;
|
|
145
|
-
private readonly oldConsumersToRegister;
|
|
106
|
+
private readonly quorumQueues;
|
|
107
|
+
private readonly publishConnections;
|
|
108
|
+
private readonly consumeConnections;
|
|
109
|
+
private readonly publishChannels;
|
|
110
|
+
private readonly publishChannelSetupPromises;
|
|
111
|
+
private readonly queuesByVhost;
|
|
112
|
+
private readonly exchangesByVhost;
|
|
113
|
+
private readonly queueSetupPromisesByVhost;
|
|
114
|
+
private readonly assertExchangePromisesByVhost;
|
|
115
|
+
private readonly consumersTagsByVhost;
|
|
116
|
+
private readonly consumersToRegisterByVhost;
|
|
146
117
|
constructor(options?: AfRabbitOptions, redisConfig?: RedisConfig | undefined);
|
|
147
118
|
private getRedisKey;
|
|
119
|
+
private isQuorumQueue;
|
|
120
|
+
private getVhostForQueue;
|
|
148
121
|
private assertVHost;
|
|
149
122
|
private shouldConsumeMessageByTimestamp;
|
|
150
123
|
ack: (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null) => (userMsg: ConsumeMessage) => Promise<void>;
|
|
151
124
|
nack: (channel: ConfirmChannel, queue: string, options: ConsumeOptions, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock?: (() => Promise<void>) | null) => (userMsg: ConsumeMessageOrNull, {
|
|
152
125
|
skipRetry
|
|
153
126
|
}?: NackOptions) => Promise<void>;
|
|
154
|
-
getConnection(connection: ConnectionData): Promise<AmqpConnectionManager>;
|
|
127
|
+
getConnection(connection: ConnectionData, vhost?: string): Promise<AmqpConnectionManager>;
|
|
128
|
+
getConnectionForVhost(vhost: string, type: "publish" | "consume"): Promise<AmqpConnectionManager>;
|
|
129
|
+
getConnectionDataForVhost(vhost: string, type: "publish" | "consume"): ConnectionData;
|
|
130
|
+
assertChannelForVhost(vhost: string, force?: boolean): Promise<ChannelWrapper>;
|
|
155
131
|
getNewChannel({
|
|
156
132
|
name,
|
|
157
133
|
onClose,
|
|
158
134
|
options,
|
|
159
135
|
connection
|
|
160
136
|
}: newChannelOpts): Promise<ChannelWrapper>;
|
|
161
|
-
|
|
162
|
-
force,
|
|
163
|
-
connection
|
|
164
|
-
}: assertChannelOpts): Promise<ChannelWrapper>;
|
|
165
|
-
assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>;
|
|
137
|
+
assertExchange(exchangeName: string, vhost?: string): Promise<Replies.AssertExchange>;
|
|
166
138
|
getQueueLength(queue: string): Promise<Replies.AssertQueue>;
|
|
167
139
|
private deleteQueue;
|
|
168
140
|
bindQueue(queue: string, exchange: string): Promise<void>;
|
|
169
|
-
setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
170
|
-
static shouldUseQuorum(queueName: string): boolean;
|
|
141
|
+
setupQueue(queueName: string, options?: Options.AssertQueue, vhost?: string): Promise<Replies.AssertQueue>;
|
|
171
142
|
assertQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
172
143
|
private saveConsumer;
|
|
173
144
|
consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
174
|
-
consumeNew(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
175
|
-
consumeOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
176
145
|
private lockRedisIfNeeded;
|
|
177
146
|
private unlockRedisIfNeeded;
|
|
178
147
|
private consumeFromRabbit;
|
|
179
148
|
consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
180
|
-
publish(exchange: string, content: any, customHeaders?: PublishOptions["headers"],
|
|
181
|
-
sendToQueue(queue: string, content: any, options?: Options.AssertQueue, customHeaders?: PublishOptions["headers"],
|
|
149
|
+
publish(exchange: string, content: any, customHeaders?: PublishOptions["headers"], _isQuorumQueue?: boolean): Promise<void>;
|
|
150
|
+
sendToQueue(queue: string, content: any, options?: Options.AssertQueue, customHeaders?: PublishOptions["headers"], _isQuorumQueue?: boolean): Promise<boolean | undefined>;
|
|
182
151
|
isConnected(): Promise<boolean>;
|
|
183
152
|
gracefulShutdown(signal: string): Promise<void>;
|
|
184
|
-
private consumeFromRabbitOld;
|
|
185
|
-
getNewChannelOld({
|
|
186
|
-
name,
|
|
187
|
-
onClose,
|
|
188
|
-
options,
|
|
189
|
-
connection
|
|
190
|
-
}: newChannelOpts): Promise<ChannelWrapper>;
|
|
191
|
-
getConnectionOld(connection: ConnectionData): Promise<AmqpConnectionManager>;
|
|
192
|
-
private saveConsumerOld;
|
|
193
|
-
assertQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
194
|
-
setupQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
195
|
-
assertChannelOld({
|
|
196
|
-
force,
|
|
197
|
-
connection
|
|
198
|
-
}: assertChannelOpts): Promise<ChannelWrapper>;
|
|
199
|
-
private deleteQueueOld;
|
|
200
|
-
assertExchangeOld(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>;
|
|
201
|
-
isConnectedOld(): Promise<boolean>;
|
|
202
153
|
private maskURL;
|
|
203
154
|
}
|
|
204
155
|
//#endregion
|
|
205
156
|
export { sendCeleryTaskViaHttp as i, IAfRabbitMq as n, RabbitMq as r, AfRabbitOptions as t };
|
|
206
|
-
//# sourceMappingURL=index-
|
|
157
|
+
//# sourceMappingURL=index-CBlhQYQ_.d.cts.map
|