@autofleet/rabbit 5.1.0-alpha.0 → 5.1.0-alpha.2
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 +3 -469
- package/dist/{index-CBlhQYQ_.d.cts → index-DG_7Rl-n.d.ts} +79 -28
- package/dist/{index-CdC0BR3j.d.ts → index-DYLqlA6K.d.cts} +79 -28
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- 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 +2 -1
- package/dist/mock/vitest.d.ts +2 -1
- 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,474 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# V5 migration
|
|
2
2
|
|
|
3
|
-
|
|
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.
|
|
3
|
+
The breaking change in this version is the removal of `zehut` from dependencies and usage as a peer-dependency.
|
|
365
4
|
The required version of zehut is now `^4.0.0`.
|
|
366
5
|
|
|
367
6
|
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.
|
|
368
7
|
|
|
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
|
|
8
|
+
Additionally, the minimum node version is now 18, due to the minimum version of node defined in `zehut`.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
1
2
|
import RedisLock from "redis-lock";
|
|
2
3
|
import { AmqpConnectionManager, ChannelWrapper, CreateChannelOpts } from "amqp-connection-manager";
|
|
3
|
-
import { PublishOptions } from "amqp-connection-manager/dist/types/ChannelWrapper";
|
|
4
|
-
import { ConfirmChannel, ConsumeMessage, Options, Replies } from "amqplib";
|
|
5
4
|
import { LoggerInstanceManager } from "@autofleet/logger";
|
|
6
5
|
import { createClient } from "redis";
|
|
6
|
+
import { PublishOptions } from "amqp-connection-manager/dist/types/ChannelWrapper";
|
|
7
|
+
import { ConfirmChannel, ConsumeMessage, Options, Replies } from "amqplib";
|
|
7
8
|
|
|
8
9
|
//#region src/lib/redis.d.ts
|
|
9
10
|
interface RedisConfig {
|
|
@@ -14,6 +15,10 @@ interface RedisConfig {
|
|
|
14
15
|
declare const getRedisInstance: (config: RedisConfig) => ReturnType<typeof createClient>;
|
|
15
16
|
//#endregion
|
|
16
17
|
//#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>;
|
|
17
22
|
interface CustomMessageHeaders {
|
|
18
23
|
redisTimestampValidationKey?: string;
|
|
19
24
|
}
|
|
@@ -27,6 +32,7 @@ interface ConsumeOptions {
|
|
|
27
32
|
useConsumeWithLock?: boolean;
|
|
28
33
|
auditContext?: any;
|
|
29
34
|
enableRabbitTrace?: boolean;
|
|
35
|
+
isQuorumQueue?: boolean;
|
|
30
36
|
}
|
|
31
37
|
interface NackOptions {
|
|
32
38
|
skipRetry?: boolean;
|
|
@@ -34,7 +40,7 @@ interface NackOptions {
|
|
|
34
40
|
type Message = Omit<ConsumeMessage, "content"> & {
|
|
35
41
|
content: any;
|
|
36
42
|
};
|
|
37
|
-
type CallbackFunction = (msg: Message, ack: () => Promise<void>, nack: (ignored: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void
|
|
43
|
+
type CallbackFunction = (msg: Message, ack: () => Promise<void>, nack: (ignored: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>, signal?: AbortSignal) => Promise<void>;
|
|
38
44
|
interface ConnectionData {
|
|
39
45
|
amqpConnection: AmqpConnectionManager | null;
|
|
40
46
|
creatingConnection: boolean;
|
|
@@ -58,7 +64,8 @@ declare function sendCeleryTaskViaHttp(data: TaskData, {
|
|
|
58
64
|
interface IAfRabbitMq {
|
|
59
65
|
ack(channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null): (userMsg: ConsumeMessage) => Promise<void>;
|
|
60
66
|
nack(channel: ConfirmChannel, queue: string, options: ConsumeOptions, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock?: () => Promise<void>): (userMsg: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>;
|
|
61
|
-
|
|
67
|
+
assertChannel(options?: assertChannelOpts): Promise<ChannelWrapper>;
|
|
68
|
+
assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>;
|
|
62
69
|
assertQueue(queueName: string, options?: Options.AssertQueue | null): Promise<Replies.AssertQueue>;
|
|
63
70
|
consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
64
71
|
consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
@@ -88,6 +95,11 @@ interface newChannelOpts {
|
|
|
88
95
|
options?: CreateChannelOpts | undefined;
|
|
89
96
|
connection: ConnectionData;
|
|
90
97
|
}
|
|
98
|
+
interface assertChannelOpts {
|
|
99
|
+
channelName?: string;
|
|
100
|
+
force?: boolean;
|
|
101
|
+
connection: ConnectionData;
|
|
102
|
+
}
|
|
91
103
|
declare class RabbitMq implements IAfRabbitMq {
|
|
92
104
|
#private;
|
|
93
105
|
readonly options: AfRabbitOptions;
|
|
@@ -97,61 +109,100 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
97
109
|
static getPublishOptions(customHeaders?: CustomMessageHeaders): PublishOptions;
|
|
98
110
|
readonly DISCONNECT_MSG = "rabbit: connection disconnect";
|
|
99
111
|
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;
|
|
100
121
|
readonly redisClient?: ReturnType<typeof getRedisInstance>;
|
|
101
122
|
readonly redisLock?: ReturnType<typeof RedisLock>;
|
|
102
|
-
|
|
123
|
+
/** A map of consumers' tags used for canceling consumption */
|
|
124
|
+
readonly consumersTags: Map<string, {
|
|
125
|
+
channel: ConfirmChannel;
|
|
126
|
+
consumerTag: string;
|
|
127
|
+
}>;
|
|
128
|
+
private readonly consumersToRegister;
|
|
103
129
|
private doesVHostExist;
|
|
104
130
|
private readonly vhost;
|
|
105
131
|
private gracefulShutdownStarted;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
132
|
+
shutdownAbortController: AbortController;
|
|
133
|
+
oldPublishChannel: ChannelWrapper | null;
|
|
134
|
+
oldPublishChannelSetupPromise: Promise<ChannelWrapper> | null;
|
|
135
|
+
readonly oldPublishConnection: ConnectionData;
|
|
136
|
+
readonly oldConsumeConnection: ConnectionData;
|
|
137
|
+
readonly oldEm: EventEmitter;
|
|
138
|
+
readonly oldExchanges: ExchangesCache;
|
|
139
|
+
readonly oldQueues: QueuesCache;
|
|
140
|
+
readonly oldQueueSetupPromises: QueueSetupPromisesDictionary;
|
|
141
|
+
readonly oldAssertExchangePromises: AssertExchangePromisesDictionary;
|
|
142
|
+
readonly oldConsumersTags: Map<string, {
|
|
143
|
+
channel: ConfirmChannel;
|
|
144
|
+
consumerTag: string;
|
|
145
|
+
}>;
|
|
146
|
+
private readonly oldConsumersToRegister;
|
|
117
147
|
constructor(options?: AfRabbitOptions, redisConfig?: RedisConfig | undefined);
|
|
118
148
|
private getRedisKey;
|
|
119
|
-
private isQuorumQueue;
|
|
120
|
-
private getVhostForQueue;
|
|
121
149
|
private assertVHost;
|
|
122
150
|
private shouldConsumeMessageByTimestamp;
|
|
123
151
|
ack: (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null) => (userMsg: ConsumeMessage) => Promise<void>;
|
|
124
152
|
nack: (channel: ConfirmChannel, queue: string, options: ConsumeOptions, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock?: (() => Promise<void>) | null) => (userMsg: ConsumeMessageOrNull, {
|
|
125
153
|
skipRetry
|
|
126
154
|
}?: NackOptions) => Promise<void>;
|
|
127
|
-
getConnection(connection: ConnectionData
|
|
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
|
+
getConnection(connection: ConnectionData): Promise<AmqpConnectionManager>;
|
|
131
156
|
getNewChannel({
|
|
132
157
|
name,
|
|
133
158
|
onClose,
|
|
134
159
|
options,
|
|
135
160
|
connection
|
|
136
161
|
}: newChannelOpts): Promise<ChannelWrapper>;
|
|
137
|
-
|
|
162
|
+
assertChannel({
|
|
163
|
+
force,
|
|
164
|
+
connection
|
|
165
|
+
}: assertChannelOpts): Promise<ChannelWrapper>;
|
|
166
|
+
assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>;
|
|
138
167
|
getQueueLength(queue: string): Promise<Replies.AssertQueue>;
|
|
139
168
|
private deleteQueue;
|
|
140
169
|
bindQueue(queue: string, exchange: string): Promise<void>;
|
|
141
|
-
setupQueue(queueName: string, options?: Options.AssertQueue
|
|
170
|
+
setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
171
|
+
static shouldUseQuorum(queueName: string): boolean;
|
|
142
172
|
assertQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
143
173
|
private saveConsumer;
|
|
144
174
|
consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
175
|
+
consumeNew(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
176
|
+
consumeOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
145
177
|
private lockRedisIfNeeded;
|
|
146
178
|
private unlockRedisIfNeeded;
|
|
147
179
|
private consumeFromRabbit;
|
|
148
180
|
consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;
|
|
149
|
-
publish(exchange: string, content: any, customHeaders?: PublishOptions["headers"],
|
|
150
|
-
sendToQueue(queue: string, content: any, options?: Options.AssertQueue, customHeaders?: PublishOptions["headers"],
|
|
181
|
+
publish(exchange: string, content: any, customHeaders?: PublishOptions["headers"], isQuorumQueue?: boolean): Promise<void>;
|
|
182
|
+
sendToQueue(queue: string, content: any, options?: Options.AssertQueue, customHeaders?: PublishOptions["headers"], isQuorumQueue?: boolean): Promise<boolean | undefined>;
|
|
151
183
|
isConnected(): Promise<boolean>;
|
|
152
184
|
gracefulShutdown(signal: string): Promise<void>;
|
|
185
|
+
private consumeFromRabbitOld;
|
|
186
|
+
getNewChannelOld({
|
|
187
|
+
name,
|
|
188
|
+
onClose,
|
|
189
|
+
options,
|
|
190
|
+
connection
|
|
191
|
+
}: newChannelOpts): Promise<ChannelWrapper>;
|
|
192
|
+
getConnectionOld(connection: ConnectionData): Promise<AmqpConnectionManager>;
|
|
193
|
+
private saveConsumerOld;
|
|
194
|
+
assertQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
195
|
+
setupQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
196
|
+
assertChannelOld({
|
|
197
|
+
force,
|
|
198
|
+
connection
|
|
199
|
+
}: assertChannelOpts): Promise<ChannelWrapper>;
|
|
200
|
+
private deleteQueueOld;
|
|
201
|
+
assertExchangeOld(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>;
|
|
202
|
+
isConnectedOld(): Promise<boolean>;
|
|
153
203
|
private maskURL;
|
|
154
204
|
}
|
|
205
|
+
type ConsumerCallbackFunction = CallbackFunction;
|
|
155
206
|
//#endregion
|
|
156
|
-
export { sendCeleryTaskViaHttp as i,
|
|
157
|
-
//# sourceMappingURL=index-
|
|
207
|
+
export { sendCeleryTaskViaHttp as a, RabbitMq as i, ConsumerCallbackFunction as n, IAfRabbitMq as r, AfRabbitOptions as t };
|
|
208
|
+
//# sourceMappingURL=index-DG_7Rl-n.d.ts.map
|