@autofleet/rabbit 2.1.6 → 2.1.8-beta1
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/.env +0 -0
- package/dist/index.d.ts +6 -29
- package/dist/index.js +21 -65
- package/dist/mock.d.ts +10 -11
- package/dist/mock.js +0 -1
- package/dump.rdb +0 -0
- package/package.json +2 -1
- package/src/index.ts +10 -4
- package/src/logger.ts +5 -0
- package/dist/redis.d.ts +0 -7
- package/dist/redis.js +0 -11
package/.env
ADDED
|
File without changes
|
package/dist/index.d.ts
CHANGED
|
@@ -2,35 +2,15 @@
|
|
|
2
2
|
import { Options } from 'amqplib';
|
|
3
3
|
import { AmqpConnectionManager, ChannelWrapper } from 'amqp-connection-manager';
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
5
|
-
import { RedisConfig } from './redis';
|
|
6
|
-
export interface IAfRabbitMq {
|
|
7
|
-
ack: any;
|
|
8
|
-
nack: any;
|
|
9
|
-
assertChannel: any;
|
|
10
|
-
assertExchange: any;
|
|
11
|
-
assertQueue: any;
|
|
12
|
-
consume: any;
|
|
13
|
-
consumeFromExchange: any;
|
|
14
|
-
publish: any;
|
|
15
|
-
sendToQueue: any;
|
|
16
|
-
redisClient?: any;
|
|
17
|
-
}
|
|
18
5
|
interface ExchangesCache {
|
|
19
6
|
[key: string]: any;
|
|
20
7
|
}
|
|
21
|
-
declare type CustomMessageHeaders = {
|
|
22
|
-
redisTimestampValidationKey?: string;
|
|
23
|
-
};
|
|
24
8
|
export interface AfRabbitOptions {
|
|
25
9
|
reconnect: boolean;
|
|
26
10
|
}
|
|
27
|
-
declare class RabbitMq
|
|
11
|
+
declare class RabbitMq {
|
|
28
12
|
static parseMsg(msg: any): any;
|
|
29
13
|
static validateName(type: string, name: string): void;
|
|
30
|
-
static getPublishOptions(customHeaders?: CustomMessageHeaders): {
|
|
31
|
-
timestamp: number;
|
|
32
|
-
headers: CustomMessageHeaders;
|
|
33
|
-
};
|
|
34
14
|
PUBLISH_TIMEOUT: number;
|
|
35
15
|
PUBLISH_ERROR_MSG: string;
|
|
36
16
|
DISCONNECT_MSG: string;
|
|
@@ -41,11 +21,9 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
41
21
|
creatingConnection: boolean;
|
|
42
22
|
exchanges: ExchangesCache;
|
|
43
23
|
options: AfRabbitOptions | undefined;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
ack: (channel: ChannelWrapper, shouldUpdateRedisTimestamp?: boolean) => (msg: any) => Promise<void>;
|
|
48
|
-
nack: (channel: ChannelWrapper, queue: string, options: any, deadQueueOptions: Options.AssertQueue) => (msg: any, { skipRetry, }?: any) => Promise<void>;
|
|
24
|
+
constructor(options?: AfRabbitOptions);
|
|
25
|
+
ack: (msg: any) => Promise<void>;
|
|
26
|
+
nack: (queue: string, options: any, deadQueueOptions: Options.AssertQueue) => (msg: any, { skipRetry, }?: any) => Promise<void>;
|
|
49
27
|
getConnection(): Promise<AmqpConnectionManager>;
|
|
50
28
|
getNewChannel(): Promise<ChannelWrapper>;
|
|
51
29
|
assertChannel(): Promise<ChannelWrapper>;
|
|
@@ -55,8 +33,7 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
55
33
|
assertQueue(queue: string, options?: Options.AssertQueue): Promise<void>;
|
|
56
34
|
consume(queue: string, callback: (msg: any, ack: Function, nack: Function) => any, options?: any): Promise<void>;
|
|
57
35
|
consumeFromExchange(queue: string, exchange: string, callback: (msg: any, ack: Function, nack: Function) => any, options?: any): Promise<void>;
|
|
58
|
-
publish(exchange: string, content: any
|
|
59
|
-
sendToQueue(queue: string, content: any, options?: any
|
|
60
|
-
isConnected(): Promise<boolean>;
|
|
36
|
+
publish(exchange: string, content: any): Promise<unknown>;
|
|
37
|
+
sendToQueue(queue: string, content: any, options?: any): Promise<void>;
|
|
61
38
|
}
|
|
62
39
|
export default RabbitMq;
|
package/dist/index.js
CHANGED
|
@@ -34,45 +34,31 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
34
34
|
/* eslint-disable @typescript-eslint/ban-ts-comment,@typescript-eslint/ban-types,@typescript-eslint/no-unused-vars,consistent-return,no-async-promise-executor,no-param-reassign,no-empty */
|
|
35
35
|
// eslint-disable-next-line max-classes-per-file
|
|
36
36
|
const bluebird = __importStar(require("bluebird"));
|
|
37
|
-
const moment_1 = __importDefault(require("moment"));
|
|
38
37
|
const amqp_connection_manager_1 = require("amqp-connection-manager");
|
|
39
38
|
const events_1 = require("events");
|
|
40
39
|
const outbreak_1 = require("@autofleet/outbreak");
|
|
41
40
|
const rabbitError_1 = __importDefault(require("./rabbitError"));
|
|
42
|
-
const redis_1 = __importDefault(require("./redis"));
|
|
43
41
|
const DEFAULT_DEAD_TTL_TWO_DAYS = 60000 * 60 * 48;
|
|
44
42
|
const defaultOptions = {
|
|
45
43
|
limit: 1,
|
|
46
44
|
retries: 1,
|
|
47
45
|
deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,
|
|
48
46
|
};
|
|
49
|
-
const SECONDS_TO_MILLISECONDS = 1000;
|
|
50
47
|
const assertExchangeFanout = (c, exchangeName) => c.assertExchange(exchangeName, 'fanout');
|
|
51
48
|
const connectionCreatedConst = 'connectionCreated';
|
|
52
49
|
class RabbitMq {
|
|
53
|
-
constructor(options
|
|
50
|
+
constructor(options) {
|
|
54
51
|
this.PUBLISH_TIMEOUT = Number(process.env.RABBITMQ_PUBLISH_TIMEOUT) || 60000;
|
|
55
52
|
this.PUBLISH_ERROR_MSG = `rabbit: publish timeout(${this.PUBLISH_TIMEOUT}ms) has pass, exchange: `;
|
|
56
53
|
this.DISCONNECT_MSG = 'rabbit: connection disconnect';
|
|
57
54
|
this.RESCONNECT_MSG = 'rabbit: reconnecting';
|
|
58
|
-
this.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const lastMessageTimestamp = yield this.redisClient.getAsync(headers.redisTimestampValidationKey);
|
|
62
|
-
return !lastMessageTimestamp || moment_1.default(parseInt(lastMessageTimestamp, 10) * SECONDS_TO_MILLISECONDS).isBefore(moment_1.default(timestamp * SECONDS_TO_MILLISECONDS));
|
|
55
|
+
this.ack = (msg) => __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
if (this.channel) {
|
|
57
|
+
yield this.channel.ack(msg);
|
|
63
58
|
}
|
|
64
|
-
return true;
|
|
65
59
|
});
|
|
66
|
-
this.
|
|
67
|
-
|
|
68
|
-
const { properties: { timestamp, headers } } = msg;
|
|
69
|
-
if (shouldUpdateRedisTimestamp && timestamp && (headers === null || headers === void 0 ? void 0 : headers.redisTimestampValidationKey) && this.redisClient) {
|
|
70
|
-
const parsedTimestamp = parseInt(timestamp, 10);
|
|
71
|
-
yield this.redisClient.setAsync(headers.redisTimestampValidationKey, parsedTimestamp, 'EX', 3600);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
this.nack = (channel, queue, options, deadQueueOptions) => (msg, { skipRetry = false, } = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
75
|
-
if (channel) {
|
|
60
|
+
this.nack = (queue, options, deadQueueOptions) => (msg, { skipRetry = false, } = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
if (this.channel) {
|
|
76
62
|
if (!skipRetry
|
|
77
63
|
&& (!msg.content['x-retry-count']
|
|
78
64
|
|| msg.content['x-retry-count'] < options.retries)) {
|
|
@@ -84,7 +70,7 @@ class RabbitMq {
|
|
|
84
70
|
yield this.assertQueue(deadQueue, deadQueueOptions);
|
|
85
71
|
yield this.sendToQueue(deadQueue, msg.content, deadQueueOptions);
|
|
86
72
|
}
|
|
87
|
-
yield channel.ack(msg);
|
|
73
|
+
yield this.channel.ack(msg);
|
|
88
74
|
}
|
|
89
75
|
});
|
|
90
76
|
this.em = new events_1.EventEmitter();
|
|
@@ -93,7 +79,6 @@ class RabbitMq {
|
|
|
93
79
|
this.creatingConnection = false;
|
|
94
80
|
this.exchanges = {};
|
|
95
81
|
this.options = options;
|
|
96
|
-
this.redisClient = redisConfig && redis_1.default(redisConfig);
|
|
97
82
|
}
|
|
98
83
|
static parseMsg(msg) {
|
|
99
84
|
let { content } = msg;
|
|
@@ -109,12 +94,6 @@ class RabbitMq {
|
|
|
109
94
|
throw new rabbitError_1.default(`error while using ${type} with no name`);
|
|
110
95
|
}
|
|
111
96
|
}
|
|
112
|
-
static getPublishOptions(customHeaders = {}) {
|
|
113
|
-
return {
|
|
114
|
-
timestamp: moment_1.default().unix(),
|
|
115
|
-
headers: customHeaders,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
97
|
getConnection() {
|
|
119
98
|
return __awaiter(this, void 0, void 0, function* () {
|
|
120
99
|
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -123,13 +102,11 @@ class RabbitMq {
|
|
|
123
102
|
return;
|
|
124
103
|
}
|
|
125
104
|
if (this.connection !== null) {
|
|
126
|
-
return
|
|
105
|
+
return this.connection;
|
|
127
106
|
}
|
|
128
107
|
this.creatingConnection = true;
|
|
129
|
-
const username = process.env.RABBITMQ_USERNAME || 'guest';
|
|
130
|
-
const password = process.env.RABBITMQ_PASSWORD || 'guest';
|
|
131
108
|
const host = process.env.RABBITMQ_SERVICE_HOST || '';
|
|
132
|
-
const connection = yield amqp_connection_manager_1.connect([`amqp://${
|
|
109
|
+
const connection = yield amqp_connection_manager_1.connect([`amqp://${host}`]);
|
|
133
110
|
this.connection = connection;
|
|
134
111
|
this.connection.on('disconnect', ({ err }) => {
|
|
135
112
|
var _a;
|
|
@@ -217,15 +194,10 @@ class RabbitMq {
|
|
|
217
194
|
yield c.assertQueue(queue);
|
|
218
195
|
yield c.prefetch(limit, true);
|
|
219
196
|
return Promise.all([
|
|
220
|
-
c.consume(queue, (msg) =>
|
|
221
|
-
const parsedMessage = RabbitMq.parseMsg(msg);
|
|
197
|
+
c.consume(queue, (msg) => {
|
|
222
198
|
outbreak_1.newTrace(outbreak_1.traceTypes.RABBIT);
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
return this.ack(channel)(msg);
|
|
226
|
-
}
|
|
227
|
-
callback(parsedMessage, this.ack(channel, true), this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
|
|
228
|
-
})),
|
|
199
|
+
callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
|
|
200
|
+
}),
|
|
229
201
|
]);
|
|
230
202
|
}));
|
|
231
203
|
});
|
|
@@ -244,47 +216,31 @@ class RabbitMq {
|
|
|
244
216
|
yield c.prefetch(limit, true);
|
|
245
217
|
return Promise.all([
|
|
246
218
|
c.bindQueue(queue, exchange, ''),
|
|
247
|
-
c.consume(queue, (msg) =>
|
|
248
|
-
const parsedMessage = RabbitMq.parseMsg(msg);
|
|
219
|
+
c.consume(queue, (msg) => {
|
|
249
220
|
outbreak_1.newTrace(outbreak_1.traceTypes.RABBIT);
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return this.ack(channel)(msg);
|
|
253
|
-
}
|
|
254
|
-
callback(parsedMessage, this.ack(channel, true), this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
|
|
255
|
-
})),
|
|
221
|
+
callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
|
|
222
|
+
}),
|
|
256
223
|
]);
|
|
257
224
|
}));
|
|
258
225
|
});
|
|
259
226
|
}
|
|
260
|
-
publish(exchange, content
|
|
227
|
+
publish(exchange, content) {
|
|
261
228
|
return __awaiter(this, void 0, void 0, function* () {
|
|
262
229
|
RabbitMq.validateName('exchange', exchange);
|
|
263
230
|
const channel = yield this.assertChannel();
|
|
264
231
|
yield this.assertExchange(exchange);
|
|
265
|
-
return new bluebird.Promise((resolve
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
return resolve();
|
|
269
|
-
}
|
|
270
|
-
catch (e) {
|
|
271
|
-
reject(e);
|
|
272
|
-
}
|
|
232
|
+
return new bluebird.Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
|
233
|
+
yield channel.publish(exchange, '', Buffer.from(JSON.stringify(content)));
|
|
234
|
+
return resolve();
|
|
273
235
|
})).timeout(this.PUBLISH_TIMEOUT, `${this.PUBLISH_ERROR_MSG}${exchange}`);
|
|
274
236
|
});
|
|
275
237
|
}
|
|
276
|
-
sendToQueue(queue, content, options
|
|
238
|
+
sendToQueue(queue, content, options) {
|
|
277
239
|
return __awaiter(this, void 0, void 0, function* () {
|
|
278
240
|
RabbitMq.validateName('queue', queue);
|
|
279
241
|
const channel = yield this.assertChannel();
|
|
280
242
|
yield this.assertQueue(queue, options);
|
|
281
|
-
return channel.sendToQueue(queue, Buffer.from(JSON.stringify(content))
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
isConnected() {
|
|
285
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
286
|
-
const connection = yield this.getConnection();
|
|
287
|
-
return connection.isConnected();
|
|
243
|
+
return channel.sendToQueue(queue, Buffer.from(JSON.stringify(content)));
|
|
288
244
|
});
|
|
289
245
|
}
|
|
290
246
|
}
|
package/dist/mock.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import 'jest';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
sendToQueue: any;
|
|
2
|
+
declare class RabbitMq {
|
|
3
|
+
ack: jest.Mock<unknown>;
|
|
4
|
+
nack: jest.Mock<unknown>;
|
|
5
|
+
assertChannel: jest.Mock<unknown>;
|
|
6
|
+
assertExchange: jest.Mock<unknown>;
|
|
7
|
+
assertQueue: jest.Mock<unknown>;
|
|
8
|
+
consume: jest.Mock<unknown>;
|
|
9
|
+
consumeFromExchange: jest.Mock<unknown>;
|
|
10
|
+
publish: jest.Mock<unknown>;
|
|
11
|
+
sendToQueue: jest.Mock<unknown>;
|
|
13
12
|
}
|
|
14
13
|
export default RabbitMq;
|
package/dist/mock.js
CHANGED
package/dump.rdb
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/rabbit",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.8-beta1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"dev": "nodemon"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
+
"@autofleet/logger": "^1.2.8",
|
|
18
19
|
"@types/amqp-connection-manager": "^2.0.10",
|
|
19
20
|
"@types/amqplib": "^0.5.16",
|
|
20
21
|
"@types/uuid": "^8.3.3",
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { ConfirmChannel, Options } from 'amqplib';
|
|
|
6
6
|
import { AmqpConnectionManager, ChannelWrapper, connect } from 'amqp-connection-manager';
|
|
7
7
|
import { EventEmitter } from 'events';
|
|
8
8
|
import { newTrace, traceTypes } from '@autofleet/outbreak';
|
|
9
|
+
import logger from './logger';
|
|
9
10
|
import RabbitError from './rabbitError';
|
|
10
11
|
import getRedisInstance, { RedisConfig } from './redis';
|
|
11
12
|
|
|
@@ -110,7 +111,10 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
110
111
|
const { properties: { timestamp, headers } } = msg;
|
|
111
112
|
if (timestamp && headers?.redisTimestampValidationKey && this.redisClient) {
|
|
112
113
|
const lastMessageTimestamp = await this.redisClient.getAsync(headers.redisTimestampValidationKey);
|
|
113
|
-
|
|
114
|
+
logger.info('rabbit: checking if should consume params', {
|
|
115
|
+
msg, timestamp, headers, lastMessageTimestamp,
|
|
116
|
+
});
|
|
117
|
+
return !lastMessageTimestamp || (parseInt(lastMessageTimestamp, 10) <= parseInt(timestamp, 10));
|
|
114
118
|
}
|
|
115
119
|
return true;
|
|
116
120
|
}
|
|
@@ -155,7 +159,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
155
159
|
async getConnection() {
|
|
156
160
|
return new Promise<AmqpConnectionManager>(async (resolve) => {
|
|
157
161
|
if (this.creatingConnection) {
|
|
158
|
-
this.em.
|
|
162
|
+
this.em.once(connectionCreatedConst, resolve);
|
|
159
163
|
return;
|
|
160
164
|
}
|
|
161
165
|
if (this.connection !== null) {
|
|
@@ -193,9 +197,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
193
197
|
return resolve(this.channel);
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
const connection: AmqpConnectionManager = await this.getConnection();
|
|
197
|
-
|
|
198
200
|
try {
|
|
201
|
+
const connection: AmqpConnectionManager = await this.getConnection();
|
|
199
202
|
if (this.channel === null) {
|
|
200
203
|
this.channel = connection.createChannel({});
|
|
201
204
|
}
|
|
@@ -252,6 +255,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
252
255
|
const parsedMessage = RabbitMq.parseMsg(msg);
|
|
253
256
|
newTrace(traceTypes.RABBIT);
|
|
254
257
|
const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
|
|
258
|
+
logger.info('rabbit: trying to consume', { queue, shouldConsume, msg });
|
|
255
259
|
if (!shouldConsume) {
|
|
256
260
|
return this.ack(channel)(msg);
|
|
257
261
|
}
|
|
@@ -282,6 +286,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
282
286
|
const parsedMessage = RabbitMq.parseMsg(msg);
|
|
283
287
|
newTrace(traceTypes.RABBIT);
|
|
284
288
|
const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
|
|
289
|
+
logger.info('rabbit: trying to consume', { queue, shouldConsume, msg });
|
|
285
290
|
if (!shouldConsume) {
|
|
286
291
|
return this.ack(channel)(msg);
|
|
287
292
|
}
|
|
@@ -312,6 +317,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
312
317
|
RabbitMq.validateName('queue', queue);
|
|
313
318
|
const channel: ChannelWrapper = await this.assertChannel();
|
|
314
319
|
await this.assertQueue(queue, options);
|
|
320
|
+
logger.info('rabbit: sending to queue', { queue, content, customHeaders });
|
|
315
321
|
return channel.sendToQueue(queue,
|
|
316
322
|
Buffer.from(JSON.stringify(content)),
|
|
317
323
|
RabbitMq.getPublishOptions(customHeaders));
|
package/src/logger.ts
ADDED
package/dist/redis.d.ts
DELETED
package/dist/redis.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const bluebird_1 = __importDefault(require("bluebird"));
|
|
7
|
-
const redis = require('redis');
|
|
8
|
-
bluebird_1.default.promisifyAll(redis.RedisClient.prototype);
|
|
9
|
-
bluebird_1.default.promisifyAll(redis.Multi.prototype);
|
|
10
|
-
const getRedisInstance = (config) => redis.createClient(config);
|
|
11
|
-
exports.default = getRedisInstance;
|