@autofleet/rabbit 3.2.26-beta.202 → 3.2.26-beta.4
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/dist/index.d.ts +17 -6
- package/dist/index.js +44 -38
- package/dist/lib/types.d.ts +1 -11
- package/package.json +1 -3
- package/src/index.ts +60 -44
- package/src/lib/types.ts +1 -12
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
|
-
import { AmqpConnectionManager, ChannelWrapper } from 'amqp-connection-manager';
|
|
3
|
+
import { AmqpConnectionManager, ChannelWrapper, CreateChannelOpts } from 'amqp-connection-manager';
|
|
4
4
|
import { ConfirmChannel, ConsumeMessage, Options, Replies } from 'amqplib';
|
|
5
5
|
import { RedisConfig } from './lib/redis';
|
|
6
6
|
import { ConnectionPurpose } from './lib/consts';
|
|
7
|
-
import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, AssertExchangePromisesDictionary, ConnectionData
|
|
7
|
+
import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, AssertExchangePromisesDictionary, ConnectionData } from './lib/types';
|
|
8
8
|
export interface IAfRabbitMq {
|
|
9
9
|
ack: any;
|
|
10
10
|
nack: any;
|
|
@@ -34,6 +34,17 @@ export interface AfRabbitOptions {
|
|
|
34
34
|
dontRetryAssert?: boolean;
|
|
35
35
|
rabbitHost?: string;
|
|
36
36
|
}
|
|
37
|
+
type newChannelOpts = {
|
|
38
|
+
name?: string;
|
|
39
|
+
onClose?: null | ((args: any | null) => void);
|
|
40
|
+
options?: CreateChannelOpts | undefined;
|
|
41
|
+
connectionPurpose?: ConnectionPurpose;
|
|
42
|
+
};
|
|
43
|
+
type assertChannelOpts = {
|
|
44
|
+
channelName?: string;
|
|
45
|
+
force?: boolean;
|
|
46
|
+
connectionPurpose?: ConnectionPurpose;
|
|
47
|
+
};
|
|
37
48
|
declare class RabbitMq implements IAfRabbitMq {
|
|
38
49
|
static parseMsg(msg: any): any;
|
|
39
50
|
static validateName(type: string, name: string): void;
|
|
@@ -73,21 +84,21 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
73
84
|
nack: (channel: ConfirmChannel, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: NackOptions) => Promise<any>;
|
|
74
85
|
getConnection(connectionPurpose: ConnectionPurpose): Promise<AmqpConnectionManager | null | undefined>;
|
|
75
86
|
getNewChannel({ name, onClose, options, connectionPurpose, }: newChannelOpts): Promise<ChannelWrapper>;
|
|
76
|
-
assertChannel({ force, connectionPurpose
|
|
87
|
+
assertChannel({ force, connectionPurpose }: assertChannelOpts): Promise<ChannelWrapper>;
|
|
77
88
|
assertExchange(exchangeName: string, options?: any): Promise<any>;
|
|
78
89
|
getQueueLength(queue: string, connectionPurpose?: ConnectionPurpose): Promise<Replies.AssertQueue>;
|
|
79
90
|
private deleteQueue;
|
|
80
91
|
bindQueue(queue: string, exchange: string): Promise<void>;
|
|
81
|
-
setupQueue(queueName: string,
|
|
92
|
+
setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
82
93
|
static shouldUseQuorum(queueName: string): boolean;
|
|
83
|
-
assertQueue(queueName: string,
|
|
94
|
+
assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any>;
|
|
84
95
|
private saveConsumer;
|
|
85
96
|
consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
|
|
86
97
|
private lockRedisIfNeeded;
|
|
87
98
|
private unlockRedisIfNeeded;
|
|
88
99
|
private consumeFromRabbit;
|
|
89
100
|
consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
|
|
90
|
-
publish(exchange: string, content: any, customHeaders?: any
|
|
101
|
+
publish(exchange: string, content: any, customHeaders?: any): Promise<boolean>;
|
|
91
102
|
sendToQueue(queue: string, content: any, options?: any, customHeaders?: any): Promise<boolean | undefined>;
|
|
92
103
|
isConnected(): Promise<boolean>;
|
|
93
104
|
gracefulShutdown(signal: string): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.sendCeleryTaskViaHttp = void 0;
|
|
8
8
|
const events_1 = require("events");
|
|
9
9
|
const util_1 = require("util");
|
|
10
|
-
const lodash_1 = require("lodash");
|
|
11
10
|
const moment_1 = __importDefault(require("moment"));
|
|
12
11
|
const redis_lock_1 = __importDefault(require("redis-lock"));
|
|
13
12
|
const amqp_connection_manager_1 = require("amqp-connection-manager");
|
|
@@ -132,7 +131,6 @@ class RabbitMq {
|
|
|
132
131
|
creatingConnection: false,
|
|
133
132
|
connectionCreatedEventName: 'publishConnectionCreated',
|
|
134
133
|
connectionFailedEventName: 'publishConnectionFailed',
|
|
135
|
-
doesChannelInitialize: false,
|
|
136
134
|
},
|
|
137
135
|
};
|
|
138
136
|
this.exchanges = {};
|
|
@@ -246,7 +244,7 @@ class RabbitMq {
|
|
|
246
244
|
if (!connection) {
|
|
247
245
|
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
248
246
|
}
|
|
249
|
-
const channel = connection.createChannel({ ...options
|
|
247
|
+
const channel = connection.createChannel({ ...options });
|
|
250
248
|
(0, events_1.once)(channel, 'close').then((args) => {
|
|
251
249
|
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
252
250
|
onClose?.(args);
|
|
@@ -261,22 +259,21 @@ class RabbitMq {
|
|
|
261
259
|
throw err;
|
|
262
260
|
}
|
|
263
261
|
}
|
|
264
|
-
async assertChannel({ force = false, connectionPurpose = consts_1.ConnectionPurpose.Consume
|
|
262
|
+
async assertChannel({ force = false, connectionPurpose = consts_1.ConnectionPurpose.Consume }) {
|
|
265
263
|
debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.publishChannel });
|
|
266
|
-
if (!this.publishChannelSetupPromise
|
|
264
|
+
if (!this.publishChannelSetupPromise) {
|
|
267
265
|
this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
268
266
|
if (this.publishChannel && !force) {
|
|
269
267
|
return resolve(this.publishChannel);
|
|
270
268
|
}
|
|
271
269
|
try {
|
|
272
|
-
const channel = await this.getNewChannel({ connectionPurpose
|
|
270
|
+
const channel = await this.getNewChannel({ connectionPurpose });
|
|
273
271
|
debug('rabbit: new channel got', { connectionPurpose, channel: this.publishChannel });
|
|
274
272
|
channel.on('error', (err) => {
|
|
275
273
|
logger_1.default.error('rabbit: channel error', { err });
|
|
276
274
|
});
|
|
277
275
|
if (connectionPurpose === consts_1.ConnectionPurpose.Publish) {
|
|
278
276
|
this.publishChannel = channel;
|
|
279
|
-
this.connectionsMap[connectionPurpose].doesChannelInitialize = true;
|
|
280
277
|
}
|
|
281
278
|
resolve(channel);
|
|
282
279
|
}
|
|
@@ -323,8 +320,9 @@ class RabbitMq {
|
|
|
323
320
|
await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
324
321
|
return channel.bindQueue(queue, exchange, '');
|
|
325
322
|
}
|
|
326
|
-
async setupQueue(queueName,
|
|
323
|
+
async setupQueue(queueName, options) {
|
|
327
324
|
let queue;
|
|
325
|
+
const connectionPurpose = consts_1.ConnectionPurpose.Publish;
|
|
328
326
|
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
329
327
|
const localeOptions = {
|
|
330
328
|
...options,
|
|
@@ -371,8 +369,8 @@ class RabbitMq {
|
|
|
371
369
|
}
|
|
372
370
|
return false;
|
|
373
371
|
}
|
|
374
|
-
async assertQueue(queueName,
|
|
375
|
-
debug('rabbit: start assert queue', {
|
|
372
|
+
async assertQueue(queueName, options) {
|
|
373
|
+
debug('rabbit: start assert queue', { queueName });
|
|
376
374
|
RabbitMq.validateName('queue', queueName);
|
|
377
375
|
if (this.queues[queueName]) {
|
|
378
376
|
delete this.queueSetupPromises[queueName];
|
|
@@ -381,8 +379,8 @@ class RabbitMq {
|
|
|
381
379
|
if (this.queueSetupPromises[queueName]) {
|
|
382
380
|
return this.queueSetupPromises[queueName];
|
|
383
381
|
}
|
|
384
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName,
|
|
385
|
-
debug('rabbit: done assert queue', {
|
|
382
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
383
|
+
debug('rabbit: done assert queue', { queueName });
|
|
386
384
|
return this.queueSetupPromises[queueName];
|
|
387
385
|
}
|
|
388
386
|
saveConsumer(queue, callback, options) {
|
|
@@ -427,11 +425,8 @@ class RabbitMq {
|
|
|
427
425
|
}
|
|
428
426
|
const channel = await this.getNewChannel({ connectionPurpose: consts_1.ConnectionPurpose.Consume });
|
|
429
427
|
return channel.addSetup(async (confirmChannel) => {
|
|
430
|
-
const q = await this.assertQueue(queue,
|
|
428
|
+
const q = await this.assertQueue(queue, optionsWithDefaults);
|
|
431
429
|
await confirmChannel.prefetch(limit, false);
|
|
432
|
-
const channelConsumerOptions = optionsWithDefaults.channelConsumeOptions
|
|
433
|
-
? (0, lodash_1.merge)(types_1.CONSUMER_DEFAULT_OPTIONS, optionsWithDefaults.channelConsumeOptions)
|
|
434
|
-
: types_1.CONSUMER_DEFAULT_OPTIONS;
|
|
435
430
|
const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
|
|
436
431
|
if (!msg) {
|
|
437
432
|
return null;
|
|
@@ -496,7 +491,7 @@ class RabbitMq {
|
|
|
496
491
|
catch (e) {
|
|
497
492
|
await localNack(msg);
|
|
498
493
|
}
|
|
499
|
-
},
|
|
494
|
+
}, types_1.CONSUMER_DEFAULT_OPTIONS);
|
|
500
495
|
if (!consumerTag) {
|
|
501
496
|
logger_1.default.error(`rabbit: failed to consume from queue ${queue}`);
|
|
502
497
|
}
|
|
@@ -524,24 +519,18 @@ class RabbitMq {
|
|
|
524
519
|
]);
|
|
525
520
|
});
|
|
526
521
|
}
|
|
527
|
-
async publish(exchange, content, customHeaders
|
|
522
|
+
async publish(exchange, content, customHeaders) {
|
|
528
523
|
debug('rabbit: start publish msg');
|
|
529
524
|
return (0, utils_1.wrapSetImmediate)(async () => {
|
|
530
525
|
RabbitMq.validateName('exchange', exchange);
|
|
531
|
-
const channel = await this.assertChannel({
|
|
532
|
-
connectionPurpose: consts_1.ConnectionPurpose.Publish,
|
|
533
|
-
newChannelOptions: options?.newChannelOptions,
|
|
534
|
-
});
|
|
526
|
+
const channel = await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
535
527
|
await this.assertExchange(exchange, { connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
536
528
|
await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
537
529
|
});
|
|
538
530
|
}
|
|
539
531
|
async sendToQueue(queue, content, options, customHeaders) {
|
|
540
532
|
try {
|
|
541
|
-
await this.assertChannel({
|
|
542
|
-
connectionPurpose: consts_1.ConnectionPurpose.Publish,
|
|
543
|
-
newChannelOptions: options?.newChannelOptions,
|
|
544
|
-
});
|
|
533
|
+
await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
545
534
|
}
|
|
546
535
|
catch (e) {
|
|
547
536
|
logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
@@ -549,7 +538,7 @@ class RabbitMq {
|
|
|
549
538
|
}
|
|
550
539
|
try {
|
|
551
540
|
RabbitMq.validateName('queue', queue);
|
|
552
|
-
await this.assertQueue(queue,
|
|
541
|
+
await this.assertQueue(queue, options);
|
|
553
542
|
}
|
|
554
543
|
catch (e) {
|
|
555
544
|
logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
@@ -565,19 +554,29 @@ class RabbitMq {
|
|
|
565
554
|
throw e;
|
|
566
555
|
}
|
|
567
556
|
}
|
|
557
|
+
// const connection = await this.getConnection();
|
|
558
|
+
// const isConnected = connection.isConnected();
|
|
559
|
+
// if (!isConnected) {
|
|
560
|
+
// logger.error('rabbit: isConnected - false');
|
|
561
|
+
// return false;
|
|
562
|
+
// }
|
|
563
|
+
// const channel: any = await this.assertChannel();
|
|
564
|
+
// try {
|
|
565
|
+
// await Promise.all([
|
|
566
|
+
// channel.waitForConnect(),
|
|
567
|
+
// ...this.consumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
|
|
568
|
+
// ]);
|
|
569
|
+
// } catch (e) {
|
|
570
|
+
// logger.error('rabbit: isConnected - false');
|
|
571
|
+
// return false;
|
|
572
|
+
// }
|
|
573
|
+
// logger.info('rabbit: isConnected - true');
|
|
574
|
+
// return true;
|
|
568
575
|
async isConnected() {
|
|
569
576
|
debug('rabbit: start is connected');
|
|
570
577
|
const isEachConnectionConnected = await Promise.all(Object.entries(this.connectionsMap).map(async ([connectionPurpose, connectionData]) => {
|
|
571
|
-
const { connection
|
|
572
|
-
if (connectionPurpose === consts_1.ConnectionPurpose.
|
|
573
|
-
|| (connectionPurpose === consts_1.ConnectionPurpose.Publish
|
|
574
|
-
&& doesChannelInitialize)) {
|
|
575
|
-
debug('rabbit: is connected inside map', { connection, connectionPurpose });
|
|
576
|
-
const isConnected = connection?.isConnected();
|
|
577
|
-
if (!isConnected) {
|
|
578
|
-
logger_1.default.error('rabbit: isConnected - false', { connectionPurpose });
|
|
579
|
-
return false;
|
|
580
|
-
}
|
|
578
|
+
const { connection } = connectionData;
|
|
579
|
+
if (connectionPurpose === consts_1.ConnectionPurpose.Publish && connection) {
|
|
581
580
|
const channel = await this.assertChannel({ connectionPurpose: connectionPurpose });
|
|
582
581
|
try {
|
|
583
582
|
await Promise.all([
|
|
@@ -590,7 +589,14 @@ class RabbitMq {
|
|
|
590
589
|
return false;
|
|
591
590
|
}
|
|
592
591
|
}
|
|
593
|
-
|
|
592
|
+
if (connection) {
|
|
593
|
+
const isConnected = connection?.isConnected();
|
|
594
|
+
if (!isConnected) {
|
|
595
|
+
logger_1.default.error('rabbit: isConnected - false', { connectionPurpose });
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
logger_1.default.info('rabbit: isConnected - true', { connectionPurpose });
|
|
599
|
+
}
|
|
594
600
|
return true;
|
|
595
601
|
}));
|
|
596
602
|
return isEachConnectionConnected.every((isConnected) => isConnected === true);
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { AmqpConnectionManager
|
|
1
|
+
import { AmqpConnectionManager } from 'amqp-connection-manager';
|
|
2
2
|
import { ConsumeMessage, Options, Replies } from 'amqplib';
|
|
3
|
-
import { ConnectionPurpose } from './consts';
|
|
4
3
|
export interface ExchangesCache {
|
|
5
4
|
[key: string]: any;
|
|
6
5
|
}
|
|
@@ -27,34 +26,25 @@ export interface ConsumeOptions {
|
|
|
27
26
|
useConsumeWithLock?: boolean;
|
|
28
27
|
auditContext?: any;
|
|
29
28
|
enableRabbitTrace?: boolean;
|
|
30
|
-
channelConsumeOptions?: Options.Consume;
|
|
31
29
|
}
|
|
32
30
|
export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Promise<any>;
|
|
33
31
|
export type newChannelOpts = {
|
|
34
32
|
name?: string;
|
|
35
33
|
onClose?: null | ((args: any | null) => void);
|
|
36
|
-
options?: CreateChannelOpts | undefined;
|
|
37
|
-
connectionPurpose?: ConnectionPurpose;
|
|
38
34
|
};
|
|
39
35
|
export type assertChannelOpts = {
|
|
40
36
|
channelName?: string;
|
|
41
37
|
force?: boolean;
|
|
42
|
-
newChannelOptions?: newChannelOpts;
|
|
43
|
-
connectionPurpose?: ConnectionPurpose;
|
|
44
38
|
};
|
|
45
39
|
export type AfConsumer = {
|
|
46
40
|
queue: string;
|
|
47
41
|
callback: CallbackFunction;
|
|
48
42
|
options: ConsumeOptions | undefined;
|
|
49
43
|
};
|
|
50
|
-
export interface PublishOptions {
|
|
51
|
-
newChannelOptions?: newChannelOpts;
|
|
52
|
-
}
|
|
53
44
|
export declare const CONSUMER_DEFAULT_OPTIONS: Options.Consume;
|
|
54
45
|
export type ConnectionData = {
|
|
55
46
|
connection: AmqpConnectionManager | null;
|
|
56
47
|
creatingConnection: boolean;
|
|
57
48
|
connectionCreatedEventName: string;
|
|
58
49
|
connectionFailedEventName: string;
|
|
59
|
-
doesChannelInitialize?: boolean;
|
|
60
50
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/rabbit",
|
|
3
|
-
"version": "3.2.26-beta.
|
|
3
|
+
"version": "3.2.26-beta.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -19,11 +19,9 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@autofleet/zehut": "^3.1.2",
|
|
22
|
-
"@types/lodash": "^4.17.16",
|
|
23
22
|
"amqp-connection-manager": "4.1.9",
|
|
24
23
|
"amqplib": "0.10.3",
|
|
25
24
|
"bluebird": "^3.7.2",
|
|
26
|
-
"lodash": "^4.17.21",
|
|
27
25
|
"moment": "^2.29.1",
|
|
28
26
|
"redis": "^3.1.2",
|
|
29
27
|
"redis-lock": "^0.1.4"
|
package/src/index.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { EventEmitter, once } from 'events';
|
|
4
4
|
import { promisify } from 'util';
|
|
5
|
-
import { merge } from 'lodash';
|
|
6
5
|
import moment from 'moment';
|
|
7
6
|
import RedisLock from 'redis-lock';
|
|
8
7
|
import {
|
|
9
|
-
AmqpConnectionManager, ChannelWrapper, connect,
|
|
8
|
+
AmqpConnectionManager, ChannelWrapper, connect, CreateChannelOpts,
|
|
10
9
|
} from 'amqp-connection-manager';
|
|
11
10
|
import {
|
|
12
11
|
ConfirmChannel, ConsumeMessage, Options, Replies,
|
|
@@ -41,9 +40,6 @@ import {
|
|
|
41
40
|
QueueSetupPromisesDictionary,
|
|
42
41
|
AssertExchangePromisesDictionary,
|
|
43
42
|
ConnectionData,
|
|
44
|
-
assertChannelOpts,
|
|
45
|
-
newChannelOpts,
|
|
46
|
-
PublishOptions,
|
|
47
43
|
} from './lib/types';
|
|
48
44
|
|
|
49
45
|
// const debug = nodeDebug('af-rabbitmq')
|
|
@@ -85,6 +81,19 @@ export interface AfRabbitOptions {
|
|
|
85
81
|
rabbitHost?: string;
|
|
86
82
|
}
|
|
87
83
|
|
|
84
|
+
type newChannelOpts = {
|
|
85
|
+
name?: string;
|
|
86
|
+
onClose?: null | ((args: any | null) => void);
|
|
87
|
+
options?: CreateChannelOpts | undefined;
|
|
88
|
+
connectionPurpose?: ConnectionPurpose,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
type assertChannelOpts = {
|
|
92
|
+
channelName?: string;
|
|
93
|
+
force?: boolean;
|
|
94
|
+
connectionPurpose?: ConnectionPurpose;
|
|
95
|
+
}
|
|
96
|
+
|
|
88
97
|
type AfConsumer = {
|
|
89
98
|
queue: string;
|
|
90
99
|
callback: CallbackFunction;
|
|
@@ -183,7 +192,6 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
183
192
|
creatingConnection: false,
|
|
184
193
|
connectionCreatedEventName: 'publishConnectionCreated',
|
|
185
194
|
connectionFailedEventName: 'publishConnectionFailed',
|
|
186
|
-
doesChannelInitialize: false,
|
|
187
195
|
},
|
|
188
196
|
};
|
|
189
197
|
this.exchanges = {};
|
|
@@ -387,7 +395,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
387
395
|
if (!connection) {
|
|
388
396
|
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
389
397
|
}
|
|
390
|
-
const channel = connection.createChannel({ ...options
|
|
398
|
+
const channel = connection.createChannel({ ...options });
|
|
391
399
|
once(channel, 'close').then((args) => {
|
|
392
400
|
logger.error(`rabbit: channel ${name} closed`);
|
|
393
401
|
onClose?.(args);
|
|
@@ -402,23 +410,22 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
402
410
|
}
|
|
403
411
|
}
|
|
404
412
|
|
|
405
|
-
async assertChannel({ force = false, connectionPurpose = ConnectionPurpose.Consume
|
|
413
|
+
async assertChannel({ force = false, connectionPurpose = ConnectionPurpose.Consume }: assertChannelOpts): Promise<ChannelWrapper> {
|
|
406
414
|
debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.publishChannel });
|
|
407
|
-
if (!this.publishChannelSetupPromise
|
|
415
|
+
if (!this.publishChannelSetupPromise) {
|
|
408
416
|
this.publishChannelSetupPromise = new Promise<ChannelWrapper>(async (resolve, reject) => {
|
|
409
417
|
if (this.publishChannel && !force) {
|
|
410
418
|
return resolve(this.publishChannel);
|
|
411
419
|
}
|
|
412
420
|
|
|
413
421
|
try {
|
|
414
|
-
const channel = await this.getNewChannel({ connectionPurpose
|
|
422
|
+
const channel = await this.getNewChannel({ connectionPurpose });
|
|
415
423
|
debug('rabbit: new channel got', { connectionPurpose, channel: this.publishChannel });
|
|
416
424
|
channel.on('error', (err) => {
|
|
417
425
|
logger.error('rabbit: channel error', { err });
|
|
418
426
|
});
|
|
419
427
|
if (connectionPurpose === ConnectionPurpose.Publish) {
|
|
420
428
|
this.publishChannel = channel;
|
|
421
|
-
this.connectionsMap[connectionPurpose].doesChannelInitialize = true;
|
|
422
429
|
}
|
|
423
430
|
resolve(channel);
|
|
424
431
|
} catch (e) {
|
|
@@ -471,8 +478,9 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
471
478
|
return channel.bindQueue(queue, exchange, '');
|
|
472
479
|
}
|
|
473
480
|
|
|
474
|
-
async setupQueue(queueName: string,
|
|
481
|
+
async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {
|
|
475
482
|
let queue: Replies.AssertQueue;
|
|
483
|
+
const connectionPurpose = ConnectionPurpose.Publish;
|
|
476
484
|
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
477
485
|
const localeOptions = {
|
|
478
486
|
...options,
|
|
@@ -524,8 +532,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
524
532
|
return false;
|
|
525
533
|
}
|
|
526
534
|
|
|
527
|
-
async assertQueue(queueName: string,
|
|
528
|
-
debug('rabbit: start assert queue', {
|
|
535
|
+
async assertQueue(queueName: string, options?: Options.AssertQueue) {
|
|
536
|
+
debug('rabbit: start assert queue', { queueName });
|
|
529
537
|
RabbitMq.validateName('queue', queueName);
|
|
530
538
|
if (this.queues[queueName]) {
|
|
531
539
|
delete this.queueSetupPromises[queueName];
|
|
@@ -536,8 +544,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
536
544
|
return this.queueSetupPromises[queueName];
|
|
537
545
|
}
|
|
538
546
|
|
|
539
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName,
|
|
540
|
-
debug('rabbit: done assert queue', {
|
|
547
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
548
|
+
debug('rabbit: done assert queue', { queueName });
|
|
541
549
|
return this.queueSetupPromises[queueName];
|
|
542
550
|
}
|
|
543
551
|
|
|
@@ -593,11 +601,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
593
601
|
}
|
|
594
602
|
const channel = await this.getNewChannel({ connectionPurpose: ConnectionPurpose.Consume });
|
|
595
603
|
return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
|
|
596
|
-
const q = await this.assertQueue(queue,
|
|
604
|
+
const q = await this.assertQueue(queue, optionsWithDefaults);
|
|
597
605
|
await confirmChannel.prefetch(limit, false);
|
|
598
|
-
const channelConsumerOptions = optionsWithDefaults.channelConsumeOptions
|
|
599
|
-
? merge(CONSUMER_DEFAULT_OPTIONS, optionsWithDefaults.channelConsumeOptions)
|
|
600
|
-
: CONSUMER_DEFAULT_OPTIONS;
|
|
601
606
|
const { consumerTag } = await confirmChannel.consume(
|
|
602
607
|
queue,
|
|
603
608
|
async (msg: ConsumeMessageOrNull) => {
|
|
@@ -673,7 +678,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
673
678
|
} catch (e) {
|
|
674
679
|
await localNack(msg);
|
|
675
680
|
}
|
|
676
|
-
},
|
|
681
|
+
}, CONSUMER_DEFAULT_OPTIONS,
|
|
677
682
|
);
|
|
678
683
|
if (!consumerTag) {
|
|
679
684
|
logger.error(`rabbit: failed to consume from queue ${queue}`);
|
|
@@ -708,14 +713,11 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
708
713
|
});
|
|
709
714
|
}
|
|
710
715
|
|
|
711
|
-
async publish(exchange: string, content: any, customHeaders?: any
|
|
716
|
+
async publish(exchange: string, content: any, customHeaders?: any): Promise<boolean> {
|
|
712
717
|
debug('rabbit: start publish msg');
|
|
713
718
|
return wrapSetImmediate(async () => {
|
|
714
719
|
RabbitMq.validateName('exchange', exchange);
|
|
715
|
-
const channel: ChannelWrapper = await this.assertChannel({
|
|
716
|
-
connectionPurpose: ConnectionPurpose.Publish,
|
|
717
|
-
newChannelOptions: options?.newChannelOptions,
|
|
718
|
-
});
|
|
720
|
+
const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
|
|
719
721
|
await this.assertExchange(exchange, { connectionPurpose: ConnectionPurpose.Publish });
|
|
720
722
|
await channel.publish(exchange, '',
|
|
721
723
|
Buffer.from(JSON.stringify(content)),
|
|
@@ -730,10 +732,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
730
732
|
customHeaders?: any,
|
|
731
733
|
): Promise<boolean | undefined> {
|
|
732
734
|
try {
|
|
733
|
-
await this.assertChannel({
|
|
734
|
-
connectionPurpose: ConnectionPurpose.Publish,
|
|
735
|
-
newChannelOptions: options?.newChannelOptions,
|
|
736
|
-
});
|
|
735
|
+
await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
|
|
737
736
|
} catch (e) {
|
|
738
737
|
logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
739
738
|
throw e;
|
|
@@ -741,7 +740,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
741
740
|
|
|
742
741
|
try {
|
|
743
742
|
RabbitMq.validateName('queue', queue);
|
|
744
|
-
await this.assertQueue(queue,
|
|
743
|
+
await this.assertQueue(queue, options);
|
|
745
744
|
} catch (e) {
|
|
746
745
|
logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
747
746
|
throw e;
|
|
@@ -759,22 +758,31 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
759
758
|
}
|
|
760
759
|
}
|
|
761
760
|
|
|
761
|
+
// const connection = await this.getConnection();
|
|
762
|
+
// const isConnected = connection.isConnected();
|
|
763
|
+
// if (!isConnected) {
|
|
764
|
+
// logger.error('rabbit: isConnected - false');
|
|
765
|
+
// return false;
|
|
766
|
+
// }
|
|
767
|
+
// const channel: any = await this.assertChannel();
|
|
768
|
+
// try {
|
|
769
|
+
// await Promise.all([
|
|
770
|
+
// channel.waitForConnect(),
|
|
771
|
+
// ...this.consumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
|
|
772
|
+
// ]);
|
|
773
|
+
// } catch (e) {
|
|
774
|
+
// logger.error('rabbit: isConnected - false');
|
|
775
|
+
// return false;
|
|
776
|
+
// }
|
|
777
|
+
// logger.info('rabbit: isConnected - true');
|
|
778
|
+
// return true;
|
|
779
|
+
|
|
762
780
|
async isConnected(): Promise<boolean> {
|
|
763
781
|
debug('rabbit: start is connected');
|
|
764
782
|
const isEachConnectionConnected = await Promise.all(
|
|
765
783
|
Object.entries(this.connectionsMap).map(async ([connectionPurpose, connectionData]) => {
|
|
766
|
-
const { connection
|
|
767
|
-
if (
|
|
768
|
-
connectionPurpose === ConnectionPurpose.Consume
|
|
769
|
-
|| (connectionPurpose === ConnectionPurpose.Publish
|
|
770
|
-
&& doesChannelInitialize
|
|
771
|
-
)) {
|
|
772
|
-
debug('rabbit: is connected inside map', { connection, connectionPurpose });
|
|
773
|
-
const isConnected = connection?.isConnected();
|
|
774
|
-
if (!isConnected) {
|
|
775
|
-
logger.error('rabbit: isConnected - false', { connectionPurpose });
|
|
776
|
-
return false;
|
|
777
|
-
}
|
|
784
|
+
const { connection } = connectionData;
|
|
785
|
+
if (connectionPurpose === ConnectionPurpose.Publish && connection) {
|
|
778
786
|
const channel: any = await this.assertChannel({ connectionPurpose: connectionPurpose as ConnectionPurpose });
|
|
779
787
|
try {
|
|
780
788
|
await Promise.all([
|
|
@@ -786,7 +794,15 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
786
794
|
return false;
|
|
787
795
|
}
|
|
788
796
|
}
|
|
789
|
-
|
|
797
|
+
|
|
798
|
+
if (connection) {
|
|
799
|
+
const isConnected = connection?.isConnected();
|
|
800
|
+
if (!isConnected) {
|
|
801
|
+
logger.error('rabbit: isConnected - false', { connectionPurpose });
|
|
802
|
+
return false;
|
|
803
|
+
}
|
|
804
|
+
logger.info('rabbit: isConnected - true', { connectionPurpose });
|
|
805
|
+
}
|
|
790
806
|
return true;
|
|
791
807
|
}),
|
|
792
808
|
);
|
package/src/lib/types.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { AmqpConnectionManager
|
|
1
|
+
import { AmqpConnectionManager } from 'amqp-connection-manager';
|
|
2
2
|
import { ConsumeMessage, Options, Replies } from 'amqplib';
|
|
3
|
-
import { ConnectionPurpose } from './consts';
|
|
4
3
|
|
|
5
4
|
export interface ExchangesCache {
|
|
6
5
|
[key: string]: any
|
|
@@ -33,7 +32,6 @@ export interface ConsumeOptions {
|
|
|
33
32
|
useConsumeWithLock?: boolean;
|
|
34
33
|
auditContext?: any;
|
|
35
34
|
enableRabbitTrace?: boolean;
|
|
36
|
-
channelConsumeOptions?: Options.Consume;
|
|
37
35
|
}
|
|
38
36
|
|
|
39
37
|
export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Promise<any>
|
|
@@ -41,14 +39,10 @@ export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Pro
|
|
|
41
39
|
export type newChannelOpts = {
|
|
42
40
|
name?: string;
|
|
43
41
|
onClose?: null | ((args: any | null) => void);
|
|
44
|
-
options?: CreateChannelOpts | undefined;
|
|
45
|
-
connectionPurpose?: ConnectionPurpose;
|
|
46
42
|
};
|
|
47
43
|
export type assertChannelOpts = {
|
|
48
44
|
channelName?: string;
|
|
49
45
|
force?: boolean;
|
|
50
|
-
newChannelOptions?: newChannelOpts;
|
|
51
|
-
connectionPurpose?: ConnectionPurpose;
|
|
52
46
|
}
|
|
53
47
|
export type AfConsumer = {
|
|
54
48
|
queue: string;
|
|
@@ -56,10 +50,6 @@ export type AfConsumer = {
|
|
|
56
50
|
options: ConsumeOptions | undefined;
|
|
57
51
|
}
|
|
58
52
|
|
|
59
|
-
export interface PublishOptions {
|
|
60
|
-
newChannelOptions?: newChannelOpts;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
53
|
const HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';
|
|
64
54
|
|
|
65
55
|
const HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';
|
|
@@ -76,5 +66,4 @@ export type ConnectionData = {
|
|
|
76
66
|
creatingConnection: boolean;
|
|
77
67
|
connectionCreatedEventName: string;
|
|
78
68
|
connectionFailedEventName: string;
|
|
79
|
-
doesChannelInitialize?: boolean;
|
|
80
69
|
};
|