@autofleet/rabbit 4.0.0-beta.0 → 4.0.1
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 +24 -17
- package/dist/index.js +303 -180
- package/dist/index.js.map +1 -0
- package/dist/lib/celery.js +1 -0
- package/dist/lib/celery.js.map +1 -0
- package/dist/lib/consts.d.ts +0 -2
- package/dist/lib/consts.js +2 -3
- package/dist/lib/consts.js.map +1 -0
- package/dist/lib/rabbitError.js +1 -0
- package/dist/lib/rabbitError.js.map +1 -0
- package/dist/lib/redis.js +1 -0
- package/dist/lib/redis.js.map +1 -0
- package/dist/lib/types.d.ts +8 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/lib/utils.js +1 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/logger.js +1 -0
- package/dist/logger.js.map +1 -0
- package/dist/{mock.d.ts → mock/index.d.ts} +1 -1
- package/dist/{mock.js → mock/index.js} +2 -1
- package/dist/mock/index.js.map +1 -0
- package/dist/mock/vitest.d.ts +13 -0
- package/dist/mock/vitest.js +18 -0
- package/dist/mock/vitest.js.map +1 -0
- package/package.json +22 -16
- package/src/index.ts +360 -203
- package/src/lib/consts.ts +0 -2
- package/src/lib/types.ts +10 -0
- package/src/{mock.ts → mock/index.ts} +2 -2
- package/src/mock/vitest.ts +24 -0
- package/tsconfig.build.json +5 -0
- package/tsconfig.json +2 -2
- package/vitest.config.ts +17 -0
- package/coverage/clover.xml +0 -669
- package/coverage/coverage-final.json +0 -9
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -131
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/src/index.html +0 -131
- package/coverage/lcov-report/src/index.ts.html +0 -3826
- package/coverage/lcov-report/src/lib/celery.ts.html +0 -352
- package/coverage/lcov-report/src/lib/consts.ts.html +0 -142
- package/coverage/lcov-report/src/lib/index.html +0 -191
- package/coverage/lcov-report/src/lib/rabbitError.ts.html +0 -103
- package/coverage/lcov-report/src/lib/redis.ts.html +0 -133
- package/coverage/lcov-report/src/lib/types.ts.html +0 -268
- package/coverage/lcov-report/src/lib/utils.ts.html +0 -142
- package/coverage/lcov-report/src/logger.ts.html +0 -100
- package/coverage/lcov.info +0 -1076
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable no-empty,consistent-return,no-async-promise-executor,@typescript-eslint/no-unused-vars */
|
|
3
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
4
|
};
|
|
6
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
6
|
exports.sendCeleryTaskViaHttp = void 0;
|
|
7
|
+
/* eslint-disable no-empty,consistent-return,no-async-promise-executor,@typescript-eslint/no-unused-vars,no-param-reassign */
|
|
8
8
|
const events_1 = require("events");
|
|
9
9
|
const util_1 = require("util");
|
|
10
10
|
const moment_1 = __importDefault(require("moment"));
|
|
@@ -12,7 +12,6 @@ const redis_lock_1 = __importDefault(require("redis-lock"));
|
|
|
12
12
|
const amqp_connection_manager_1 = require("amqp-connection-manager");
|
|
13
13
|
const zehut_1 = require("@autofleet/zehut");
|
|
14
14
|
const node_crypto_1 = require("node:crypto");
|
|
15
|
-
const axios_1 = __importDefault(require("axios"));
|
|
16
15
|
const logger_1 = __importDefault(require("./logger"));
|
|
17
16
|
const rabbitError_1 = __importDefault(require("./lib/rabbitError"));
|
|
18
17
|
const redis_1 = __importDefault(require("./lib/redis"));
|
|
@@ -22,6 +21,8 @@ const types_1 = require("./lib/types");
|
|
|
22
21
|
// const debug = nodeDebug('af-rabbitmq')
|
|
23
22
|
const debug = logger_1.default.debug.bind(logger_1.default);
|
|
24
23
|
const PUBLISH_TIMEOUT = 1000 * 10;
|
|
24
|
+
// TODO: [QUORUM-PHASE-3] Delete this env var
|
|
25
|
+
const { DISABLE_QUORUM_QUEUES_CONSUME, DISABLE_QUORUM_QUEUES_PUBLISH, } = process.env;
|
|
25
26
|
const HEARTBEAT = '60';
|
|
26
27
|
class RabbitMq {
|
|
27
28
|
static parseMsg(msg) {
|
|
@@ -61,48 +62,50 @@ class RabbitMq {
|
|
|
61
62
|
this.DISCONNECT_MSG = 'rabbit: connection disconnect';
|
|
62
63
|
this.RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';
|
|
63
64
|
this.consumers = [];
|
|
64
|
-
this.
|
|
65
|
+
this.doesVHostExist = false;
|
|
66
|
+
this.vhost = 'quorum-vhost';
|
|
65
67
|
this.oldConsumers = [];
|
|
66
68
|
this.assertVHost = async () => {
|
|
67
|
-
if (this.
|
|
69
|
+
if (this.doesVHostExist) {
|
|
68
70
|
return;
|
|
69
71
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
username: process.env.RABBITMQ_USERNAME || 'guest',
|
|
77
|
-
password: process.env.RABBITMQ_PASSWORD || 'guest',
|
|
78
|
-
},
|
|
72
|
+
const username = process.env.RABBITMQ_USERNAME || 'guest';
|
|
73
|
+
const password = process.env.RABBITMQ_PASSWORD || 'guest';
|
|
74
|
+
const credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
|
75
|
+
const headers = {
|
|
76
|
+
Authorization: `Basic ${credentials}`,
|
|
77
|
+
'Content-Type': 'application/json',
|
|
79
78
|
};
|
|
80
|
-
const rabbitHost = `http://${(this.options
|
|
79
|
+
const rabbitHost = `http://${(this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost').split(':')[0]}:15672`;
|
|
80
|
+
const url = `${rabbitHost}/api/vhosts/${encodeURIComponent(this.vhost)}`;
|
|
81
81
|
try {
|
|
82
|
-
const response = await
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
const response = await fetch(url, {
|
|
83
|
+
method: 'GET',
|
|
84
|
+
headers,
|
|
85
|
+
});
|
|
86
|
+
if (response.status === 200) {
|
|
87
|
+
this.doesVHostExist = true;
|
|
88
|
+
logger_1.default.info('Vhost exists', { vhost: this.vhost });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (response.status !== 404) {
|
|
92
|
+
logger_1.default.error('Failed to check vhost', { response });
|
|
93
|
+
throw new rabbitError_1.default('Failed to check vhost');
|
|
94
|
+
}
|
|
95
|
+
const createResponse = await fetch(url, {
|
|
96
|
+
method: 'PUT',
|
|
97
|
+
headers,
|
|
98
|
+
body: JSON.stringify({ default_queue_type: 'quorum' }),
|
|
99
|
+
});
|
|
100
|
+
if (!createResponse.ok) {
|
|
101
|
+
logger_1.default.error('Failed to create vhost', { response: createResponse });
|
|
102
|
+
throw new rabbitError_1.default('Failed to create vhost');
|
|
85
103
|
}
|
|
86
|
-
this.
|
|
87
|
-
logger_1.default.info('Vhost
|
|
104
|
+
this.doesVHostExist = true;
|
|
105
|
+
logger_1.default.info('Vhost created', { vhost: this.vhost });
|
|
88
106
|
}
|
|
89
107
|
catch (error) {
|
|
90
|
-
|
|
91
|
-
if (error instanceof axios_1.default.AxiosError && error.response?.status === 404) {
|
|
92
|
-
try {
|
|
93
|
-
await axios_1.default.put(`${rabbitHost}/api/vhosts/${encodeURIComponent(vhost)}`, {
|
|
94
|
-
default_queue_type: 'quorum',
|
|
95
|
-
}, auth);
|
|
96
|
-
this.isVHostExist = true;
|
|
97
|
-
logger_1.default.info('Vhost created', { vhost: this.options?.vhost });
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
catch (createError) {
|
|
101
|
-
logger_1.default.error('Failed to create vhost', { error: createError });
|
|
102
|
-
throw createError;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
logger_1.default.error('Failed to check vhost', { error });
|
|
108
|
+
logger_1.default.error('Failed to check or create vhost', { error });
|
|
106
109
|
throw error;
|
|
107
110
|
}
|
|
108
111
|
};
|
|
@@ -135,11 +138,11 @@ class RabbitMq {
|
|
|
135
138
|
await this.unlockRedisIfNeeded(releaseLock);
|
|
136
139
|
if (channel && msg) {
|
|
137
140
|
if (!skipRetry
|
|
138
|
-
&& (!msg.properties.headers[consts_1.RETRY_HEADER]
|
|
141
|
+
&& (!msg.properties.headers?.[consts_1.RETRY_HEADER]
|
|
139
142
|
|| parseInt(msg.properties.headers[consts_1.RETRY_HEADER], 10) < options.retries)) {
|
|
140
143
|
await this.sendToQueue(queue, RabbitMq.parseMsg(msg).content, options, {
|
|
141
144
|
...msg.properties.headers,
|
|
142
|
-
[consts_1.RETRY_HEADER]: msg.properties.headers[consts_1.RETRY_HEADER]
|
|
145
|
+
[consts_1.RETRY_HEADER]: msg.properties.headers?.[consts_1.RETRY_HEADER]
|
|
143
146
|
? msg.properties.headers[consts_1.RETRY_HEADER] + 1
|
|
144
147
|
: 1,
|
|
145
148
|
});
|
|
@@ -148,7 +151,7 @@ class RabbitMq {
|
|
|
148
151
|
const deadQueue = `${queue}-dead`;
|
|
149
152
|
await this.sendToQueue(deadQueue, RabbitMq.parseMsg(msg).content, deadQueueOptions, {
|
|
150
153
|
...msg.properties.headers,
|
|
151
|
-
[consts_1.RETRY_HEADER]: msg.properties.headers[consts_1.RETRY_HEADER]
|
|
154
|
+
[consts_1.RETRY_HEADER]: msg.properties.headers?.[consts_1.RETRY_HEADER]
|
|
152
155
|
? msg.properties.headers[consts_1.RETRY_HEADER] + 1
|
|
153
156
|
: 1,
|
|
154
157
|
});
|
|
@@ -162,10 +165,34 @@ class RabbitMq {
|
|
|
162
165
|
});
|
|
163
166
|
}
|
|
164
167
|
};
|
|
168
|
+
this.maskURL = (url) => {
|
|
169
|
+
try {
|
|
170
|
+
const urlObj = new URL(url);
|
|
171
|
+
urlObj.username = '***';
|
|
172
|
+
urlObj.password = '***';
|
|
173
|
+
return urlObj.toString();
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return url;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
165
179
|
this.em = new events_1.EventEmitter();
|
|
166
|
-
this.
|
|
180
|
+
this.publishChannel = null;
|
|
167
181
|
this.publishChannelSetupPromise = null;
|
|
168
|
-
this.
|
|
182
|
+
this.publishConnection = {
|
|
183
|
+
amqpConnection: null,
|
|
184
|
+
creatingConnection: false,
|
|
185
|
+
connectionCreatedEventName: 'publishConnectionCreated',
|
|
186
|
+
connectionFailedEventName: 'publishConnectionFailed',
|
|
187
|
+
blockReconnect: false,
|
|
188
|
+
};
|
|
189
|
+
this.consumeConnection = {
|
|
190
|
+
amqpConnection: null,
|
|
191
|
+
creatingConnection: false,
|
|
192
|
+
connectionCreatedEventName: 'consumeConnectionCreated',
|
|
193
|
+
connectionFailedEventName: 'consumeConnectionFailed',
|
|
194
|
+
blockReconnect: false,
|
|
195
|
+
};
|
|
169
196
|
this.creatingConnection = false;
|
|
170
197
|
this.exchanges = {};
|
|
171
198
|
this.queues = {};
|
|
@@ -173,9 +200,6 @@ class RabbitMq {
|
|
|
173
200
|
this.assertExchangePromises = {};
|
|
174
201
|
this.consumers = [];
|
|
175
202
|
this.options = options;
|
|
176
|
-
if (!options?.vhost) {
|
|
177
|
-
this.options.vhost = process.env.VHOST_NAME || 'quorum-vhost';
|
|
178
|
-
}
|
|
179
203
|
this.redisClient = redisConfig && (0, redis_1.default)(redisConfig);
|
|
180
204
|
if (this.redisClient) {
|
|
181
205
|
this.redisLock = (0, util_1.promisify)((0, redis_lock_1.default)(this.redisClient));
|
|
@@ -190,11 +214,24 @@ class RabbitMq {
|
|
|
190
214
|
await this.gracefulShutdown('SIGINT');
|
|
191
215
|
});
|
|
192
216
|
}
|
|
193
|
-
// TODO:
|
|
217
|
+
// TODO: [QUORUM-PHASE-3] Delete the old properties that we use for the old consumers and publishers
|
|
194
218
|
this.oldEm = new events_1.EventEmitter();
|
|
195
|
-
this.
|
|
219
|
+
this.oldPublishChannel = null;
|
|
196
220
|
this.oldPublishChannelSetupPromise = null;
|
|
197
|
-
this.
|
|
221
|
+
this.oldPublishConnection = {
|
|
222
|
+
amqpConnection: null,
|
|
223
|
+
creatingConnection: false,
|
|
224
|
+
connectionCreatedEventName: 'oldPublishConnectionCreated',
|
|
225
|
+
connectionFailedEventName: 'oldPublishConnectionFailed',
|
|
226
|
+
blockReconnect: false,
|
|
227
|
+
};
|
|
228
|
+
this.oldConsumeConnection = {
|
|
229
|
+
amqpConnection: null,
|
|
230
|
+
creatingConnection: false,
|
|
231
|
+
connectionCreatedEventName: 'oldConsumeConnectionCreated',
|
|
232
|
+
connectionFailedEventName: 'oldConsumeConnectionFailed',
|
|
233
|
+
blockReconnect: false,
|
|
234
|
+
};
|
|
198
235
|
this.oldCreatingConnection = false;
|
|
199
236
|
this.oldExchanges = {};
|
|
200
237
|
this.oldQueues = {};
|
|
@@ -203,30 +240,31 @@ class RabbitMq {
|
|
|
203
240
|
this.oldConsumers = [];
|
|
204
241
|
this.oldConsumersTags = [];
|
|
205
242
|
}
|
|
206
|
-
async getConnection() {
|
|
243
|
+
async getConnection(connection) {
|
|
207
244
|
return new Promise(async (resolve, reject) => {
|
|
208
|
-
|
|
245
|
+
const { amqpConnection: connectionLocal, creatingConnection, connectionCreatedEventName, connectionFailedEventName, blockReconnect, } = connection;
|
|
246
|
+
if (blockReconnect) {
|
|
209
247
|
debug('rabbit: block reconnect');
|
|
210
248
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
211
249
|
// @ts-ignore
|
|
212
250
|
return resolve();
|
|
213
251
|
}
|
|
214
|
-
if (
|
|
215
|
-
if (this.options?.disableReconnect ||
|
|
252
|
+
if (connectionLocal !== null) {
|
|
253
|
+
if (this.options?.disableReconnect || connectionLocal?.isConnected()) {
|
|
216
254
|
debug('rabbit: connection - is connected');
|
|
217
255
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
218
256
|
// @ts-ignore
|
|
219
|
-
return resolve(
|
|
257
|
+
return resolve(connectionLocal);
|
|
220
258
|
}
|
|
221
259
|
debug('rabbit: connection - reconnecting');
|
|
222
260
|
}
|
|
223
|
-
if (
|
|
261
|
+
if (creatingConnection) {
|
|
224
262
|
debug('rabbit: creating connection emi');
|
|
225
|
-
this.em.once(
|
|
226
|
-
this.em.once(
|
|
263
|
+
this.em.once(connectionCreatedEventName, resolve);
|
|
264
|
+
this.em.once(connectionFailedEventName, reject);
|
|
227
265
|
return;
|
|
228
266
|
}
|
|
229
|
-
|
|
267
|
+
connection.creatingConnection = true;
|
|
230
268
|
let isResolved = false;
|
|
231
269
|
// It is import to use it as a function and not as a variable
|
|
232
270
|
// because of k8s changes the env variables
|
|
@@ -236,61 +274,63 @@ class RabbitMq {
|
|
|
236
274
|
const password = process.env.RABBITMQ_PASSWORD || 'guest';
|
|
237
275
|
const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';
|
|
238
276
|
debug('rabbit: creating connection', { host, userName, HEARTBEAT });
|
|
239
|
-
return [`amqp://${userName}:${password}@${host}/${this.
|
|
277
|
+
return [`amqp://${userName}:${password}@${host}/${this.vhost}?heartbeat=${HEARTBEAT}`];
|
|
240
278
|
};
|
|
241
279
|
const defaultUrls = findServers();
|
|
242
|
-
const
|
|
280
|
+
const newConnection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
|
|
243
281
|
findServers,
|
|
244
282
|
});
|
|
245
|
-
|
|
246
|
-
|
|
283
|
+
connection.amqpConnection = newConnection;
|
|
284
|
+
newConnection.on('error', (err) => {
|
|
247
285
|
logger_1.default.error('rabbit: connection error', { err });
|
|
248
286
|
if (!isResolved) {
|
|
249
287
|
isResolved = true;
|
|
250
288
|
reject(err);
|
|
251
|
-
this.em.emit(
|
|
289
|
+
this.em.emit(connectionFailedEventName, err);
|
|
252
290
|
}
|
|
253
291
|
});
|
|
254
|
-
|
|
292
|
+
newConnection.on('connectFailed', (err) => {
|
|
255
293
|
this.consumersTags = [];
|
|
256
|
-
|
|
294
|
+
if (typeof err.url === 'string') {
|
|
295
|
+
err.url = this.maskURL(err.url);
|
|
296
|
+
}
|
|
297
|
+
logger_1.default.error('rabbit: connection connectFailed', { err, advice: 'Check if the vhost exist', vhost: this.vhost });
|
|
257
298
|
if (!isResolved) {
|
|
258
299
|
isResolved = true;
|
|
259
300
|
reject(err);
|
|
260
|
-
this.em.emit(
|
|
301
|
+
this.em.emit(connectionFailedEventName, err);
|
|
261
302
|
}
|
|
262
303
|
});
|
|
263
|
-
|
|
264
|
-
// this.channel = null;
|
|
304
|
+
newConnection.on('disconnect', ({ err }) => {
|
|
265
305
|
this.consumersTags = [];
|
|
266
306
|
debug('rabbit: connection closed');
|
|
267
307
|
if (this.options?.disableReconnect) {
|
|
268
308
|
logger_1.default.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
|
|
269
|
-
|
|
309
|
+
connection.blockReconnect = true;
|
|
270
310
|
}
|
|
271
311
|
else {
|
|
272
312
|
logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
273
313
|
}
|
|
274
314
|
});
|
|
275
|
-
|
|
315
|
+
newConnection.once('connect', async () => {
|
|
276
316
|
debug('rabbit: connection established');
|
|
277
|
-
|
|
278
|
-
this.em.emit(
|
|
317
|
+
connection.creatingConnection = false;
|
|
318
|
+
this.em.emit(connectionCreatedEventName, newConnection);
|
|
279
319
|
isResolved = true;
|
|
280
|
-
resolve(
|
|
320
|
+
resolve(newConnection);
|
|
281
321
|
});
|
|
282
322
|
});
|
|
283
323
|
}
|
|
284
|
-
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}
|
|
285
|
-
let
|
|
324
|
+
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}, connection, }) {
|
|
325
|
+
let localConnection;
|
|
286
326
|
try {
|
|
287
|
-
|
|
327
|
+
localConnection = await this.getConnection(connection);
|
|
288
328
|
}
|
|
289
329
|
catch (e) {
|
|
290
330
|
logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
291
331
|
throw e;
|
|
292
332
|
}
|
|
293
|
-
const channel =
|
|
333
|
+
const channel = localConnection?.createChannel({ ...options });
|
|
294
334
|
(0, events_1.once)(channel, 'close').then((args) => {
|
|
295
335
|
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
296
336
|
onClose?.(args);
|
|
@@ -305,18 +345,20 @@ class RabbitMq {
|
|
|
305
345
|
throw err;
|
|
306
346
|
}
|
|
307
347
|
}
|
|
308
|
-
async assertChannel({ force = false
|
|
348
|
+
async assertChannel({ force = false, connection }) {
|
|
309
349
|
if (!this.publishChannelSetupPromise) {
|
|
310
350
|
this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
311
|
-
if (this.
|
|
312
|
-
return resolve(this.
|
|
351
|
+
if (this.publishChannel && !force) {
|
|
352
|
+
return resolve(this.publishChannel);
|
|
313
353
|
}
|
|
314
354
|
try {
|
|
315
|
-
const channel = await this.getNewChannel({});
|
|
355
|
+
const channel = await this.getNewChannel({ connection });
|
|
316
356
|
channel.on('error', (err) => {
|
|
317
357
|
logger_1.default.error('rabbit: channel error', { err });
|
|
318
358
|
});
|
|
319
|
-
this.
|
|
359
|
+
if (this.publishConnection === connection) {
|
|
360
|
+
this.publishChannel = channel;
|
|
361
|
+
}
|
|
320
362
|
resolve(channel);
|
|
321
363
|
}
|
|
322
364
|
catch (e) {
|
|
@@ -326,8 +368,8 @@ class RabbitMq {
|
|
|
326
368
|
}
|
|
327
369
|
return this.publishChannelSetupPromise;
|
|
328
370
|
}
|
|
329
|
-
async assertExchange(exchangeName,
|
|
330
|
-
const channel = await this.assertChannel();
|
|
371
|
+
async assertExchange(exchangeName, connection) {
|
|
372
|
+
const channel = await this.assertChannel({ connection });
|
|
331
373
|
if (this.exchanges[exchangeName]) {
|
|
332
374
|
delete this.assertExchangePromises[exchangeName];
|
|
333
375
|
return this.exchanges[exchangeName];
|
|
@@ -339,32 +381,31 @@ class RabbitMq {
|
|
|
339
381
|
this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];
|
|
340
382
|
return this.exchanges[exchangeName];
|
|
341
383
|
}
|
|
342
|
-
// TODO: Change the implementation to the new one
|
|
343
384
|
async getQueueLength(queue) {
|
|
344
385
|
RabbitMq.validateName('queue', queue);
|
|
345
|
-
const {
|
|
386
|
+
const { publishChannel: channel } = this;
|
|
346
387
|
if (!channel) {
|
|
347
|
-
throw new
|
|
388
|
+
throw new rabbitError_1.default('channel is not defined');
|
|
348
389
|
}
|
|
349
|
-
debug('rabbit: getting queue length', { queue, connected: this.
|
|
390
|
+
debug('rabbit: getting queue length', { queue, connected: this.publishConnection.amqpConnection?.isConnected() });
|
|
350
391
|
return channel?.checkQueue(queue);
|
|
351
392
|
}
|
|
352
|
-
async deleteQueue(queue) {
|
|
393
|
+
async deleteQueue(queue, connection) {
|
|
353
394
|
RabbitMq.validateName('queue', queue);
|
|
354
|
-
const channel = await this.assertChannel();
|
|
395
|
+
const channel = await this.assertChannel({ connection });
|
|
355
396
|
logger_1.default.info('rabbit: deleting queue', { queue });
|
|
356
397
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
357
398
|
debug('queue deleted', deleteQueueRes);
|
|
358
399
|
return deleteQueueRes;
|
|
359
400
|
}
|
|
360
|
-
// TODO: Change the implementation to the new one
|
|
361
401
|
async bindQueue(queue, exchange) {
|
|
362
|
-
const channel = await this.
|
|
402
|
+
const channel = await this.assertChannel({ connection: this.publishConnection });
|
|
363
403
|
await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
364
404
|
return channel.bindQueue(queue, exchange, '');
|
|
365
405
|
}
|
|
366
406
|
async setupQueue(queueName, options) {
|
|
367
407
|
let queue;
|
|
408
|
+
const connection = this.publishConnection;
|
|
368
409
|
const localeOptions = {
|
|
369
410
|
...options,
|
|
370
411
|
durable: true,
|
|
@@ -375,7 +416,7 @@ class RabbitMq {
|
|
|
375
416
|
},
|
|
376
417
|
};
|
|
377
418
|
try {
|
|
378
|
-
const channel = await this.assertChannel();
|
|
419
|
+
const channel = await this.assertChannel({ connection });
|
|
379
420
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
380
421
|
await channel.addSetup(async (setupChannel) => {
|
|
381
422
|
await setupChannel.assertQueue(queueName, localeOptions);
|
|
@@ -387,8 +428,8 @@ class RabbitMq {
|
|
|
387
428
|
logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
388
429
|
if (!this.options?.dontRetryAssert) {
|
|
389
430
|
debug('retrying assertQueue', { queueName });
|
|
390
|
-
const channel = await this.assertChannel({ force: true });
|
|
391
|
-
await this.deleteQueue(queueName);
|
|
431
|
+
const channel = await this.assertChannel({ force: true, connection });
|
|
432
|
+
await this.deleteQueue(queueName, connection);
|
|
392
433
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
393
434
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
394
435
|
debug('retrying assertQueue->channel.assertQueue', { queueName });
|
|
@@ -401,7 +442,7 @@ class RabbitMq {
|
|
|
401
442
|
this.queues[queueName] = queue;
|
|
402
443
|
return queue;
|
|
403
444
|
}
|
|
404
|
-
// TODO: Can be deleted after deleting the old consumers
|
|
445
|
+
// TODO: [QUORUM-PHASE-3] Can be deleted after deleting the old consumers and publishers because all the queues are created us quorum queues
|
|
405
446
|
static shouldUseQuorum(queueName) {
|
|
406
447
|
const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;
|
|
407
448
|
if (envQuorumQueuesWhitelist === '*') {
|
|
@@ -438,18 +479,18 @@ class RabbitMq {
|
|
|
438
479
|
}
|
|
439
480
|
// Used by the microservices to consume messages from the queue
|
|
440
481
|
async consume(queue, callback, options) {
|
|
441
|
-
// TODO:
|
|
442
|
-
if (options?.isQuorumQueue !== false) {
|
|
482
|
+
// TODO: [QUORUM-PHASE-3] Use only the implementation of consumeNew and delete consumeNew and consumeOld
|
|
483
|
+
if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {
|
|
443
484
|
await this.assertVHost();
|
|
444
485
|
await this.consumeNew(queue, callback, options);
|
|
445
486
|
}
|
|
446
487
|
await this.consumeOld(queue, callback, options);
|
|
447
488
|
}
|
|
448
|
-
// TODO:
|
|
489
|
+
// TODO: [QUORUM-PHASE-3] Delete consumeNew we do not use it anymore
|
|
449
490
|
async consumeNew(queue, callback, options) {
|
|
450
491
|
await this.consumeFromRabbit(queue, callback, options);
|
|
451
492
|
}
|
|
452
|
-
// TODO:
|
|
493
|
+
// TODO: [QUORUM-PHASE-3] Delete consumeOld we do not use it anymore
|
|
453
494
|
async consumeOld(queue, callback, options) {
|
|
454
495
|
await this.consumeFromRabbitOld(queue, callback, options);
|
|
455
496
|
}
|
|
@@ -475,11 +516,11 @@ class RabbitMq {
|
|
|
475
516
|
const { limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace, } = optionsWithDefaults;
|
|
476
517
|
if (useConsumeWithLock) {
|
|
477
518
|
if (!this.redisLock) {
|
|
478
|
-
throw new
|
|
519
|
+
throw new rabbitError_1.default('Usage of consumeWithLock requires RedisInstance');
|
|
479
520
|
}
|
|
480
521
|
logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
481
522
|
}
|
|
482
|
-
const channel = await this.getNewChannel({});
|
|
523
|
+
const channel = await this.getNewChannel({ connection: this.consumeConnection });
|
|
483
524
|
return channel.addSetup(async (confirmChannel) => {
|
|
484
525
|
const q = await this.assertQueue(queue, optionsWithDefaults);
|
|
485
526
|
await confirmChannel.prefetch(limit, false);
|
|
@@ -563,10 +604,14 @@ class RabbitMq {
|
|
|
563
604
|
RabbitMq.validateName('exchange', exchange);
|
|
564
605
|
RabbitMq.validateName('queue', queue);
|
|
565
606
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
566
|
-
if
|
|
607
|
+
// TODO: [QUORUM-PHASE-3] Delete the if statement after all the queues are created as quorum queues
|
|
608
|
+
if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {
|
|
567
609
|
await this.assertVHost();
|
|
568
610
|
await this.saveConsumer(queue, callback, options);
|
|
569
|
-
const channel = await this.getNewChannel({
|
|
611
|
+
const channel = await this.getNewChannel({
|
|
612
|
+
name: `consume-exchange-${exchange}-queue-${queue}`,
|
|
613
|
+
connection: this.consumeConnection,
|
|
614
|
+
});
|
|
570
615
|
await channel.addSetup(async (c) => {
|
|
571
616
|
const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
|
|
572
617
|
await c.assertQueue(queue);
|
|
@@ -578,9 +623,12 @@ class RabbitMq {
|
|
|
578
623
|
]);
|
|
579
624
|
});
|
|
580
625
|
}
|
|
581
|
-
// TODO:
|
|
626
|
+
// TODO: [QUORUM-PHASE-3] Delete the old implementation
|
|
582
627
|
await this.saveConsumerOld(queue, callback, options);
|
|
583
|
-
const channelOld = await this.getNewChannelOld({
|
|
628
|
+
const channelOld = await this.getNewChannelOld({
|
|
629
|
+
name: `consume-exchange-${exchange}-queue-${queue}-old`,
|
|
630
|
+
connection: this.oldConsumeConnection,
|
|
631
|
+
});
|
|
584
632
|
await channelOld.addSetup(async (c) => {
|
|
585
633
|
const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
|
|
586
634
|
await c.assertQueue(queue);
|
|
@@ -593,68 +641,109 @@ class RabbitMq {
|
|
|
593
641
|
});
|
|
594
642
|
}
|
|
595
643
|
// Used by the microservices to publish messages to the exchange
|
|
596
|
-
// TODO:
|
|
597
|
-
async publish(exchange, content, customHeaders) {
|
|
644
|
+
// TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues
|
|
645
|
+
async publish(exchange, content, customHeaders, isQuorumQueue = true) {
|
|
646
|
+
if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {
|
|
647
|
+
return (0, utils_1.wrapSetImmediate)(async () => {
|
|
648
|
+
await this.assertVHost();
|
|
649
|
+
RabbitMq.validateName('exchange', exchange);
|
|
650
|
+
const channel = await this.assertChannel({ connection: this.publishConnection });
|
|
651
|
+
await this.assertExchange(exchange, this.publishConnection);
|
|
652
|
+
await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
// TODO: [QUORUM-PHASE-3] Delete the old implementation
|
|
598
656
|
return (0, utils_1.wrapSetImmediate)(async () => {
|
|
599
657
|
RabbitMq.validateName('exchange', exchange);
|
|
600
|
-
const channel = await this.assertChannelOld();
|
|
601
|
-
await this.assertExchangeOld(exchange);
|
|
658
|
+
const channel = await this.assertChannelOld({ connection: this.oldPublishConnection });
|
|
659
|
+
await this.assertExchangeOld(exchange, this.oldPublishConnection);
|
|
602
660
|
await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
603
661
|
});
|
|
604
662
|
}
|
|
605
663
|
// Used by the microservices to send messages to the queue
|
|
606
|
-
// TODO:
|
|
607
|
-
async sendToQueue(queue, content, options, customHeaders) {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
664
|
+
// TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues
|
|
665
|
+
async sendToQueue(queue, content, options, customHeaders, isQuorumQueue = true) {
|
|
666
|
+
if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {
|
|
667
|
+
try {
|
|
668
|
+
await this.assertVHost();
|
|
669
|
+
await this.assertChannel({ connection: this.publishConnection });
|
|
670
|
+
}
|
|
671
|
+
catch (e) {
|
|
672
|
+
logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
673
|
+
throw e;
|
|
674
|
+
}
|
|
675
|
+
try {
|
|
676
|
+
RabbitMq.validateName('queue', queue);
|
|
677
|
+
await this.assertQueue(queue, options);
|
|
678
|
+
}
|
|
679
|
+
catch (e) {
|
|
680
|
+
logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
681
|
+
throw e;
|
|
682
|
+
}
|
|
683
|
+
try {
|
|
684
|
+
const res = await this.publishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
685
|
+
debug(`rabbit: sending to queue ${queue}`, { res });
|
|
686
|
+
return res;
|
|
687
|
+
}
|
|
688
|
+
catch (e) {
|
|
689
|
+
const isConnected = await this.isConnected();
|
|
690
|
+
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
691
|
+
throw e;
|
|
692
|
+
}
|
|
627
693
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
694
|
+
else {
|
|
695
|
+
try {
|
|
696
|
+
await this.assertChannelOld({ connection: this.oldPublishConnection });
|
|
697
|
+
}
|
|
698
|
+
catch (e) {
|
|
699
|
+
logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
700
|
+
throw e;
|
|
701
|
+
}
|
|
702
|
+
try {
|
|
703
|
+
RabbitMq.validateName('queue', queue);
|
|
704
|
+
await this.assertQueueOld(queue, options);
|
|
705
|
+
}
|
|
706
|
+
catch (e) {
|
|
707
|
+
logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
708
|
+
throw e;
|
|
709
|
+
}
|
|
710
|
+
try {
|
|
711
|
+
const res = await this.oldPublishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
712
|
+
debug(`rabbit: sending to queue ${queue}`, { res });
|
|
713
|
+
return res;
|
|
714
|
+
}
|
|
715
|
+
catch (e) {
|
|
716
|
+
const isConnected = await this.isConnectedOld();
|
|
717
|
+
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
718
|
+
throw e;
|
|
719
|
+
}
|
|
632
720
|
}
|
|
633
721
|
}
|
|
634
|
-
// TODO: After changing the publish to the new implementation change the from the old to the new
|
|
635
722
|
async isConnected() {
|
|
636
|
-
|
|
637
|
-
const
|
|
723
|
+
debug('rabbit: start old is connected');
|
|
724
|
+
const consumeConnection = await this.getConnection(this.consumeConnection);
|
|
725
|
+
const publishConnection = await this.getConnection(this.publishConnection);
|
|
726
|
+
const isConnected = consumeConnection.isConnected() && publishConnection.isConnected();
|
|
638
727
|
if (!isConnected) {
|
|
639
|
-
logger_1.default.error('rabbit: isConnected - false');
|
|
728
|
+
logger_1.default.error('rabbit: old isConnected - false');
|
|
640
729
|
return false;
|
|
641
730
|
}
|
|
642
|
-
const channel = await this.
|
|
731
|
+
const channel = await this.assertChannel({ connection: this.publishConnection });
|
|
643
732
|
try {
|
|
644
733
|
await Promise.all([
|
|
645
734
|
channel.waitForConnect(),
|
|
646
|
-
...this.
|
|
735
|
+
...this.consumers.map((c) => channel.checkQueue(c.queue)),
|
|
647
736
|
]);
|
|
648
737
|
}
|
|
649
738
|
catch (e) {
|
|
650
739
|
logger_1.default.error('rabbit: isConnected - false');
|
|
651
740
|
return false;
|
|
652
741
|
}
|
|
653
|
-
logger_1.default.
|
|
742
|
+
logger_1.default.debug('rabbit: isConnected - true');
|
|
654
743
|
return true;
|
|
655
744
|
}
|
|
656
745
|
async gracefulShutdown(signal) {
|
|
657
|
-
// TODO:
|
|
746
|
+
// TODO: [QUORUM-PHASE-3] Delete the old implementation they are not needed anymore
|
|
658
747
|
const tagsNumber = this.consumersTags.length + this.oldConsumersTags.length;
|
|
659
748
|
logger_1.default.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);
|
|
660
749
|
const cancelTagPromises = this.consumersTags.map(([channel, tag]) => channel.cancel(tag));
|
|
@@ -679,11 +768,11 @@ class RabbitMq {
|
|
|
679
768
|
const { limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace, } = optionsWithDefaults;
|
|
680
769
|
if (useConsumeWithLock) {
|
|
681
770
|
if (!this.redisLock) {
|
|
682
|
-
throw new
|
|
771
|
+
throw new rabbitError_1.default('Usage of consumeWithLock requires RedisInstance');
|
|
683
772
|
}
|
|
684
773
|
logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
685
774
|
}
|
|
686
|
-
const channel = await this.getNewChannelOld({});
|
|
775
|
+
const channel = await this.getNewChannelOld({ connection: this.oldConsumeConnection });
|
|
687
776
|
return channel.addSetup(async (confirmChannel) => {
|
|
688
777
|
const q = await this.assertQueueOld(queue, optionsWithDefaults);
|
|
689
778
|
await confirmChannel.prefetch(limit, false);
|
|
@@ -761,17 +850,20 @@ class RabbitMq {
|
|
|
761
850
|
}
|
|
762
851
|
});
|
|
763
852
|
}
|
|
764
|
-
// TODO:
|
|
765
|
-
async getNewChannelOld({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}
|
|
766
|
-
let
|
|
853
|
+
// TODO: [QUORUM-PHASE-3] Delete all the function under this line.
|
|
854
|
+
async getNewChannelOld({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}, connection, }) {
|
|
855
|
+
let localConnection;
|
|
767
856
|
try {
|
|
768
|
-
|
|
857
|
+
localConnection = await this.getConnectionOld(connection);
|
|
769
858
|
}
|
|
770
859
|
catch (e) {
|
|
771
860
|
logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
772
861
|
throw e;
|
|
773
862
|
}
|
|
774
|
-
|
|
863
|
+
if (!localConnection) {
|
|
864
|
+
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
865
|
+
}
|
|
866
|
+
const channel = localConnection?.createChannel({ ...options });
|
|
775
867
|
(0, events_1.once)(channel, 'close').then((args) => {
|
|
776
868
|
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
777
869
|
onClose?.(args);
|
|
@@ -786,30 +878,31 @@ class RabbitMq {
|
|
|
786
878
|
throw err;
|
|
787
879
|
}
|
|
788
880
|
}
|
|
789
|
-
async getConnectionOld() {
|
|
881
|
+
async getConnectionOld(connection) {
|
|
790
882
|
return new Promise(async (resolve, reject) => {
|
|
791
|
-
|
|
883
|
+
const { amqpConnection: connectionLocal, creatingConnection, connectionCreatedEventName, connectionFailedEventName, blockReconnect, } = connection;
|
|
884
|
+
if (blockReconnect) {
|
|
792
885
|
debug('rabbit: block reconnect');
|
|
793
886
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
794
887
|
// @ts-ignore
|
|
795
888
|
return resolve();
|
|
796
889
|
}
|
|
797
|
-
if (
|
|
798
|
-
if (this.options?.disableReconnect ||
|
|
890
|
+
if (connectionLocal !== null) {
|
|
891
|
+
if (this.options?.disableReconnect || connectionLocal?.isConnected()) {
|
|
799
892
|
debug('rabbit: connection - is connected');
|
|
800
893
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
801
894
|
// @ts-ignore
|
|
802
|
-
return resolve(
|
|
895
|
+
return resolve(connectionLocal);
|
|
803
896
|
}
|
|
804
897
|
debug('rabbit: connection - reconnecting');
|
|
805
898
|
}
|
|
806
|
-
if (
|
|
899
|
+
if (creatingConnection) {
|
|
807
900
|
debug('rabbit: creating connection emi');
|
|
808
|
-
this.oldEm.once(
|
|
809
|
-
this.oldEm.once(
|
|
901
|
+
this.oldEm.once(connectionCreatedEventName, resolve);
|
|
902
|
+
this.oldEm.once(connectionFailedEventName, reject);
|
|
810
903
|
return;
|
|
811
904
|
}
|
|
812
|
-
|
|
905
|
+
connection.creatingConnection = true;
|
|
813
906
|
let isResolved = false;
|
|
814
907
|
// It is import to use it as a function and not as a variable
|
|
815
908
|
// because of k8s changes the env variables
|
|
@@ -822,44 +915,47 @@ class RabbitMq {
|
|
|
822
915
|
return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
|
|
823
916
|
};
|
|
824
917
|
const defaultUrls = findServers();
|
|
825
|
-
const
|
|
918
|
+
const newConnection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
|
|
826
919
|
findServers,
|
|
827
920
|
});
|
|
828
|
-
|
|
829
|
-
|
|
921
|
+
connection.amqpConnection = newConnection;
|
|
922
|
+
newConnection.on('error', (err) => {
|
|
830
923
|
logger_1.default.error('rabbit: connection error', { err });
|
|
831
924
|
if (!isResolved) {
|
|
832
925
|
isResolved = true;
|
|
833
926
|
reject(err);
|
|
834
|
-
this.oldEm.emit(
|
|
927
|
+
this.oldEm.emit(connectionFailedEventName, err);
|
|
835
928
|
}
|
|
836
929
|
});
|
|
837
|
-
|
|
930
|
+
newConnection.on('connectFailed', (err) => {
|
|
838
931
|
this.oldConsumersTags = [];
|
|
932
|
+
if (typeof err.url === 'string') {
|
|
933
|
+
err.url = this.maskURL(err.url);
|
|
934
|
+
}
|
|
839
935
|
logger_1.default.error('rabbit: connection connectFailed', { err });
|
|
840
936
|
if (!isResolved) {
|
|
841
937
|
isResolved = true;
|
|
842
938
|
reject(err);
|
|
843
|
-
this.oldEm.emit(
|
|
939
|
+
this.oldEm.emit(connectionFailedEventName, err);
|
|
844
940
|
}
|
|
845
941
|
});
|
|
846
|
-
|
|
942
|
+
newConnection.on('disconnect', ({ err }) => {
|
|
847
943
|
this.oldConsumersTags = [];
|
|
848
944
|
debug('rabbit: connection closed');
|
|
849
945
|
if (this.options?.disableReconnect) {
|
|
850
946
|
logger_1.default.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
|
|
851
|
-
|
|
947
|
+
connection.blockReconnect = true;
|
|
852
948
|
}
|
|
853
949
|
else {
|
|
854
950
|
logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
855
951
|
}
|
|
856
952
|
});
|
|
857
|
-
|
|
953
|
+
newConnection.once('connect', async () => {
|
|
858
954
|
debug('rabbit: connection established');
|
|
859
|
-
|
|
860
|
-
this.oldEm.emit(
|
|
955
|
+
connection.creatingConnection = false;
|
|
956
|
+
this.oldEm.emit(connectionCreatedEventName, newConnection);
|
|
861
957
|
isResolved = true;
|
|
862
|
-
resolve(
|
|
958
|
+
resolve(newConnection);
|
|
863
959
|
});
|
|
864
960
|
});
|
|
865
961
|
}
|
|
@@ -888,6 +984,7 @@ class RabbitMq {
|
|
|
888
984
|
}
|
|
889
985
|
async setupQueueOld(queueName, options) {
|
|
890
986
|
let queue;
|
|
987
|
+
const connection = this.oldPublishConnection;
|
|
891
988
|
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
892
989
|
const localeOptions = {
|
|
893
990
|
...options,
|
|
@@ -899,7 +996,7 @@ class RabbitMq {
|
|
|
899
996
|
},
|
|
900
997
|
};
|
|
901
998
|
try {
|
|
902
|
-
const channel = await this.assertChannelOld();
|
|
999
|
+
const channel = await this.assertChannelOld({ connection });
|
|
903
1000
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
904
1001
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
905
1002
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -909,8 +1006,8 @@ class RabbitMq {
|
|
|
909
1006
|
logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
910
1007
|
if (!this.options?.dontRetryAssert) {
|
|
911
1008
|
debug('retrying assertQueue', { queueName });
|
|
912
|
-
const channel = await this.assertChannelOld({ force: true });
|
|
913
|
-
await this.deleteQueueOld(queueName);
|
|
1009
|
+
const channel = await this.assertChannelOld({ force: true, connection });
|
|
1010
|
+
await this.deleteQueueOld(queueName, connection);
|
|
914
1011
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
915
1012
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
916
1013
|
debug('retrying assertQueue->channel.assertQueue', { queueName });
|
|
@@ -923,18 +1020,20 @@ class RabbitMq {
|
|
|
923
1020
|
this.oldQueues[queueName] = queue;
|
|
924
1021
|
return queue;
|
|
925
1022
|
}
|
|
926
|
-
async assertChannelOld({ force = false
|
|
1023
|
+
async assertChannelOld({ force = false, connection }) {
|
|
927
1024
|
if (!this.oldPublishChannelSetupPromise) {
|
|
928
1025
|
this.oldPublishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
929
|
-
if (this.
|
|
930
|
-
return resolve(this.
|
|
1026
|
+
if (this.oldPublishChannel && !force) {
|
|
1027
|
+
return resolve(this.oldPublishChannel);
|
|
931
1028
|
}
|
|
932
1029
|
try {
|
|
933
|
-
const channel = await this.getNewChannelOld({});
|
|
1030
|
+
const channel = await this.getNewChannelOld({ connection });
|
|
934
1031
|
channel.on('error', (err) => {
|
|
935
1032
|
logger_1.default.error('rabbit: channel error', { err });
|
|
936
1033
|
});
|
|
937
|
-
this.
|
|
1034
|
+
if (this.oldPublishConnection === connection) {
|
|
1035
|
+
this.oldPublishChannel = channel;
|
|
1036
|
+
}
|
|
938
1037
|
resolve(channel);
|
|
939
1038
|
}
|
|
940
1039
|
catch (e) {
|
|
@@ -944,16 +1043,16 @@ class RabbitMq {
|
|
|
944
1043
|
}
|
|
945
1044
|
return this.oldPublishChannelSetupPromise;
|
|
946
1045
|
}
|
|
947
|
-
async deleteQueueOld(queue) {
|
|
1046
|
+
async deleteQueueOld(queue, connection) {
|
|
948
1047
|
RabbitMq.validateName('queue', queue);
|
|
949
|
-
const channel = await this.assertChannelOld();
|
|
1048
|
+
const channel = await this.assertChannelOld({ connection });
|
|
950
1049
|
logger_1.default.info('rabbit: deleting queue', { queue });
|
|
951
1050
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
952
1051
|
debug('queue deleted', deleteQueueRes);
|
|
953
1052
|
return deleteQueueRes;
|
|
954
1053
|
}
|
|
955
|
-
async assertExchangeOld(exchangeName,
|
|
956
|
-
const channel = await this.assertChannelOld();
|
|
1054
|
+
async assertExchangeOld(exchangeName, connection) {
|
|
1055
|
+
const channel = await this.assertChannelOld({ connection });
|
|
957
1056
|
if (this.oldExchanges[exchangeName]) {
|
|
958
1057
|
delete this.oldAssertExchangePromises[exchangeName];
|
|
959
1058
|
return this.oldExchanges[exchangeName];
|
|
@@ -965,7 +1064,31 @@ class RabbitMq {
|
|
|
965
1064
|
this.oldExchanges[exchangeName] = await this.oldAssertExchangePromises[exchangeName];
|
|
966
1065
|
return this.oldExchanges[exchangeName];
|
|
967
1066
|
}
|
|
1067
|
+
async isConnectedOld() {
|
|
1068
|
+
debug('rabbit: start old is connected');
|
|
1069
|
+
const oldConsumeConnection = await this.getConnectionOld(this.oldConsumeConnection);
|
|
1070
|
+
const oldPublishConnection = await this.getConnectionOld(this.oldPublishConnection);
|
|
1071
|
+
const oldIsConnected = oldConsumeConnection.isConnected() && oldPublishConnection.isConnected();
|
|
1072
|
+
if (!oldIsConnected) {
|
|
1073
|
+
logger_1.default.error('rabbit: old isConnected - false');
|
|
1074
|
+
return false;
|
|
1075
|
+
}
|
|
1076
|
+
const oldChannel = await this.assertChannelOld({ connection: this.oldPublishConnection });
|
|
1077
|
+
try {
|
|
1078
|
+
await Promise.all([
|
|
1079
|
+
oldChannel.waitForConnect(),
|
|
1080
|
+
...this.oldConsumers.map((c) => oldChannel.checkQueue(c.queue)),
|
|
1081
|
+
]);
|
|
1082
|
+
}
|
|
1083
|
+
catch (e) {
|
|
1084
|
+
logger_1.default.error('rabbit: old isConnected - false');
|
|
1085
|
+
return false;
|
|
1086
|
+
}
|
|
1087
|
+
logger_1.default.debug('rabbit: old isConnected - true');
|
|
1088
|
+
return true;
|
|
1089
|
+
}
|
|
968
1090
|
}
|
|
969
1091
|
exports.default = RabbitMq;
|
|
970
1092
|
var celery_1 = require("./lib/celery");
|
|
971
1093
|
Object.defineProperty(exports, "sendCeleryTaskViaHttp", { enumerable: true, get: function () { return celery_1.sendCeleryTaskViaHttp; } });
|
|
1094
|
+
//# sourceMappingURL=index.js.map
|