@diia-inhouse/diia-queue 13.3.4 → 14.0.11
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/constants.js +9 -9
- package/dist/index.d.ts +27 -0
- package/dist/index.js +23 -21
- package/dist/interfaces/deps.d.ts +30 -0
- package/dist/interfaces/externalCommunicator.d.ts +58 -0
- package/dist/interfaces/index.d.ts +95 -0
- package/dist/interfaces/index.js +7 -30
- package/dist/interfaces/messageBrokerServiceConfig.d.ts +80 -0
- package/dist/interfaces/messageBrokerServiceConfig.js +27 -24
- package/dist/interfaces/messageHandler.d.ts +6 -0
- package/dist/interfaces/metrics/index.d.ts +23 -0
- package/dist/interfaces/metrics/index.js +12 -16
- package/dist/interfaces/options.d.ts +52 -0
- package/dist/interfaces/providers/rabbitmq/amqpConnection.d.ts +33 -0
- package/dist/interfaces/providers/rabbitmq/amqpConnection.js +14 -17
- package/dist/interfaces/providers/rabbitmq/amqpPublisher.d.ts +20 -0
- package/dist/interfaces/providers/rabbitmq/index.d.ts +107 -0
- package/dist/interfaces/providers/rabbitmq/index.js +35 -47
- package/dist/interfaces/queueConfig/configs.d.ts +47 -0
- package/dist/interfaces/queueConfig/configs.js +8 -9
- package/dist/interfaces/queueConfig/index.d.ts +1 -0
- package/dist/interfaces/queueContext.d.ts +8 -0
- package/dist/interfaces/queueStatus.d.ts +15 -0
- package/dist/interfaces/queueStatus.js +8 -9
- package/dist/metrics/index.js +5 -8
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.js +6 -22
- package/dist/providers/rabbitmq/amqpAsserter.d.ts +53 -0
- package/dist/providers/rabbitmq/amqpAsserter.js +369 -416
- package/dist/providers/rabbitmq/amqpConnection.d.ts +24 -0
- package/dist/providers/rabbitmq/amqpConnection.js +97 -150
- package/dist/providers/rabbitmq/amqpListener.d.ts +47 -0
- package/dist/providers/rabbitmq/amqpListener.js +218 -225
- package/dist/providers/rabbitmq/amqpPublisher.d.ts +38 -0
- package/dist/providers/rabbitmq/amqpPublisher.js +184 -191
- package/dist/providers/rabbitmq/index.d.ts +56 -0
- package/dist/providers/rabbitmq/index.js +161 -186
- package/dist/services/communicator.d.ts +66 -0
- package/dist/services/communicator.js +164 -186
- package/dist/services/eventBus.d.ts +25 -0
- package/dist/services/eventBus.js +45 -57
- package/dist/services/eventCommunicator.js +75 -124
- package/dist/services/eventMessageHandler.d.ts +27 -0
- package/dist/services/eventMessageHandler.js +124 -129
- package/dist/services/eventMessageValidator.d.ts +13 -0
- package/dist/services/eventMessageValidator.js +59 -44
- package/dist/services/externalCommunicator.d.ts +114 -0
- package/dist/services/externalCommunicator.js +149 -140
- package/dist/services/externalEventBus.d.ts +39 -0
- package/dist/services/externalEventBus.js +144 -162
- package/dist/services/index.d.ts +8 -0
- package/dist/services/index.js +10 -26
- package/dist/services/metrics.d.ts +15 -0
- package/dist/services/metrics.js +46 -49
- package/dist/services/optionsBuilder.d.ts +14 -0
- package/dist/services/optionsBuilder.js +43 -58
- package/dist/services/queue.d.ts +29 -0
- package/dist/services/queue.js +78 -93
- package/dist/services/scheduledTask.d.ts +30 -0
- package/dist/services/scheduledTask.js +60 -68
- package/dist/services/task.d.ts +33 -0
- package/dist/services/task.js +160 -176
- package/dist/utils.js +7 -11
- package/package.json +44 -50
- package/dist/constants.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/interfaces/deps.js +0 -3
- package/dist/interfaces/deps.js.map +0 -1
- package/dist/interfaces/externalCommunicator.js +0 -3
- package/dist/interfaces/externalCommunicator.js.map +0 -1
- package/dist/interfaces/index.js.map +0 -1
- package/dist/interfaces/messageBrokerServiceConfig.js.map +0 -1
- package/dist/interfaces/messageHandler.js +0 -3
- package/dist/interfaces/messageHandler.js.map +0 -1
- package/dist/interfaces/metrics/index.js.map +0 -1
- package/dist/interfaces/options.js +0 -3
- package/dist/interfaces/options.js.map +0 -1
- package/dist/interfaces/providers/rabbitmq/amqpConnection.js.map +0 -1
- package/dist/interfaces/providers/rabbitmq/amqpPublisher.js +0 -4
- package/dist/interfaces/providers/rabbitmq/amqpPublisher.js.map +0 -1
- package/dist/interfaces/providers/rabbitmq/index.js.map +0 -1
- package/dist/interfaces/queueConfig/configs.js.map +0 -1
- package/dist/interfaces/queueConfig/index.js +0 -18
- package/dist/interfaces/queueConfig/index.js.map +0 -1
- package/dist/interfaces/queueContext.js +0 -3
- package/dist/interfaces/queueContext.js.map +0 -1
- package/dist/interfaces/queueStatus.js.map +0 -1
- package/dist/interfaces/services/eventMessageHandler.js +0 -3
- package/dist/interfaces/services/eventMessageHandler.js.map +0 -1
- package/dist/metrics/index.js.map +0 -1
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/rabbitmq/amqpAsserter.js.map +0 -1
- package/dist/providers/rabbitmq/amqpConnection.js.map +0 -1
- package/dist/providers/rabbitmq/amqpListener.js.map +0 -1
- package/dist/providers/rabbitmq/amqpPublisher.js.map +0 -1
- package/dist/providers/rabbitmq/index.js.map +0 -1
- package/dist/services/communicator.js.map +0 -1
- package/dist/services/eventBus.js.map +0 -1
- package/dist/services/eventCommunicator.js.map +0 -1
- package/dist/services/eventMessageHandler.js.map +0 -1
- package/dist/services/eventMessageValidator.js.map +0 -1
- package/dist/services/externalCommunicator.js.map +0 -1
- package/dist/services/externalEventBus.js.map +0 -1
- package/dist/services/index.js.map +0 -1
- package/dist/services/metrics.js.map +0 -1
- package/dist/services/optionsBuilder.js.map +0 -1
- package/dist/services/queue.js.map +0 -1
- package/dist/services/scheduledTask.js.map +0 -1
- package/dist/services/task.js.map +0 -1
- package/dist/types/constants.d.ts +0 -8
- package/dist/types/index.d.ts +0 -4
- package/dist/types/interfaces/deps.d.ts +0 -26
- package/dist/types/interfaces/externalCommunicator.d.ts +0 -54
- package/dist/types/interfaces/index.d.ts +0 -99
- package/dist/types/interfaces/messageBrokerServiceConfig.d.ts +0 -79
- package/dist/types/interfaces/messageHandler.d.ts +0 -2
- package/dist/types/interfaces/metrics/index.d.ts +0 -20
- package/dist/types/interfaces/options.d.ts +0 -49
- package/dist/types/interfaces/providers/rabbitmq/amqpConnection.d.ts +0 -29
- package/dist/types/interfaces/providers/rabbitmq/amqpPublisher.d.ts +0 -16
- package/dist/types/interfaces/providers/rabbitmq/index.d.ts +0 -114
- package/dist/types/interfaces/queueConfig/configs.d.ts +0 -47
- package/dist/types/interfaces/queueConfig/index.d.ts +0 -1
- package/dist/types/interfaces/queueContext.d.ts +0 -4
- package/dist/types/interfaces/queueStatus.d.ts +0 -11
- package/dist/types/interfaces/services/eventMessageHandler.d.ts +0 -5
- package/dist/types/metrics/index.d.ts +0 -3
- package/dist/types/providers/index.d.ts +0 -5
- package/dist/types/providers/rabbitmq/amqpAsserter.d.ts +0 -49
- package/dist/types/providers/rabbitmq/amqpConnection.d.ts +0 -20
- package/dist/types/providers/rabbitmq/amqpListener.d.ts +0 -42
- package/dist/types/providers/rabbitmq/amqpPublisher.d.ts +0 -34
- package/dist/types/providers/rabbitmq/index.d.ts +0 -52
- package/dist/types/services/communicator.d.ts +0 -57
- package/dist/types/services/eventBus.d.ts +0 -20
- package/dist/types/services/eventCommunicator.d.ts +0 -15
- package/dist/types/services/eventMessageHandler.d.ts +0 -19
- package/dist/types/services/eventMessageValidator.d.ts +0 -9
- package/dist/types/services/externalCommunicator.d.ts +0 -110
- package/dist/types/services/externalEventBus.d.ts +0 -33
- package/dist/types/services/index.d.ts +0 -9
- package/dist/types/services/metrics.d.ts +0 -11
- package/dist/types/services/optionsBuilder.d.ts +0 -10
- package/dist/types/services/queue.d.ts +0 -23
- package/dist/types/services/scheduledTask.d.ts +0 -25
- package/dist/types/services/task.d.ts +0 -28
- package/dist/types/utils.d.ts +0 -3
- package/dist/utils.js.map +0 -1
|
@@ -1,417 +1,370 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Arguments } from "../../interfaces/providers/rabbitmq/index.js";
|
|
2
|
+
import { AmqpConnectionEventNames } from "../../interfaces/providers/rabbitmq/amqpConnection.js";
|
|
3
|
+
import { QueueTypes } from "../../interfaces/messageBrokerServiceConfig.js";
|
|
4
|
+
import "../../interfaces/index.js";
|
|
5
|
+
import constants_default from "../../constants.js";
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
|
+
//#region src/providers/rabbitmq/amqpAsserter.ts
|
|
8
|
+
var AmqpAsserter = class AmqpAsserter {
|
|
9
|
+
connection;
|
|
10
|
+
logger;
|
|
11
|
+
declareOptions;
|
|
12
|
+
static PrefixAlternate = "Alternate";
|
|
13
|
+
defaultExchangeType = "topic";
|
|
14
|
+
defaultQueueOptions = { durable: true };
|
|
15
|
+
defaultExchangeOptions = {
|
|
16
|
+
durable: true,
|
|
17
|
+
autoDelete: false
|
|
18
|
+
};
|
|
19
|
+
defaultDeclareOptions = {
|
|
20
|
+
assertQueues: true,
|
|
21
|
+
assertExchanges: true
|
|
22
|
+
};
|
|
23
|
+
channel;
|
|
24
|
+
channelName = "asserterChannel";
|
|
25
|
+
constructor(connection, logger, declareOptions = {}) {
|
|
26
|
+
this.connection = connection;
|
|
27
|
+
this.logger = logger;
|
|
28
|
+
this.declareOptions = declareOptions;
|
|
29
|
+
declareOptions.assertQueues ??= this.defaultDeclareOptions.assertQueues;
|
|
30
|
+
declareOptions.assertExchanges ??= this.defaultDeclareOptions.assertExchanges;
|
|
31
|
+
}
|
|
32
|
+
async init(exchangesOptions = [], queuesOptions = []) {
|
|
33
|
+
if (!this.channel) {
|
|
34
|
+
await this.initChannel();
|
|
35
|
+
this.connection.on(AmqpConnectionEventNames.Ready, async () => {
|
|
36
|
+
await this.initChannel();
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
await this.assertExchanges(exchangesOptions);
|
|
40
|
+
await this.declareQueues(queuesOptions, exchangesOptions);
|
|
41
|
+
}
|
|
42
|
+
async declareQueuesByJSON(declarationConfigPath) {
|
|
43
|
+
const { exchangesOptions, queuesOptions } = await this.readConfig(declarationConfigPath);
|
|
44
|
+
await this.declareQueues(queuesOptions, exchangesOptions);
|
|
45
|
+
}
|
|
46
|
+
async declareQueues(queuesOptions = [], exchangesOptions = []) {
|
|
47
|
+
for (const queueOptions of queuesOptions) {
|
|
48
|
+
const { name: queueName, redeclareOptions: { redeclare } = {} } = queueOptions;
|
|
49
|
+
if (redeclare) try {
|
|
50
|
+
await this.redeclareQueue(queueOptions, exchangesOptions);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
this.logger.error(`Error while redeclaring queue ${queueName}`, { err });
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
else await this.assertQueue(queueOptions);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async redeclareQueue(queueOptions, exchangesOptions) {
|
|
59
|
+
const { bindTo = [], redeclareOptions = {} } = queueOptions;
|
|
60
|
+
const { redeclare } = redeclareOptions;
|
|
61
|
+
if (!redeclare) return false;
|
|
62
|
+
const redeclareQueueOptions = this.prepareRedeclareQueueOptions(queueOptions, redeclareOptions);
|
|
63
|
+
const { name: queueName } = redeclareQueueOptions;
|
|
64
|
+
this.logger.info(`Queue ${queueName} is being to be redeclared`, { options: redeclareQueueOptions });
|
|
65
|
+
const alternateExchangesOptions = await this.assertAlternateExchanges(redeclareQueueOptions, exchangesOptions);
|
|
66
|
+
const { name: alternateQueueName } = await this.assertAlternateQueue(redeclareQueueOptions, alternateExchangesOptions);
|
|
67
|
+
await this.unbindQueueFromExchanges({
|
|
68
|
+
bindTo: [],
|
|
69
|
+
name: queueName,
|
|
70
|
+
unbindFrom: bindTo.map(({ exchangeName, routingKey }) => ({
|
|
71
|
+
routingKey,
|
|
72
|
+
exchangeName,
|
|
73
|
+
unbind: true
|
|
74
|
+
}))
|
|
75
|
+
});
|
|
76
|
+
const { name: tempQueueName, bindTo: tempBindTo } = await this.assertTemporaryQueue(redeclareQueueOptions);
|
|
77
|
+
await this.transferMessageBetweenQueues(queueName, tempQueueName);
|
|
78
|
+
try {
|
|
79
|
+
await this.deleteQueue(queueName);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
if (!(err instanceof Error)) throw err;
|
|
82
|
+
if (err.message.includes("NOT_FOUND - no queue")) {
|
|
83
|
+
await this.deleteQueues([alternateQueueName, tempQueueName]);
|
|
84
|
+
await this.deleteExchanges(Object.values(alternateExchangesOptions));
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
await this.assertQueue(redeclareQueueOptions);
|
|
89
|
+
await this.unbindQueueFromExchanges({
|
|
90
|
+
bindTo: [],
|
|
91
|
+
name: tempQueueName,
|
|
92
|
+
unbindFrom: tempBindTo.map(({ exchangeName, routingKey }) => ({
|
|
93
|
+
routingKey,
|
|
94
|
+
exchangeName,
|
|
95
|
+
unbind: true
|
|
96
|
+
}))
|
|
97
|
+
});
|
|
98
|
+
await this.transferMessageBetweenQueues(tempQueueName, queueName);
|
|
99
|
+
await this.transferMessageBetweenQueues(alternateQueueName, queueName);
|
|
100
|
+
await this.deleteQueue(tempQueueName);
|
|
101
|
+
await this.deleteQueue(alternateQueueName);
|
|
102
|
+
await this.deleteExchanges(Object.values(alternateExchangesOptions));
|
|
103
|
+
this.logger.info(`Queue ${queueName} has been redeclared successfully`);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
async transferMessageBetweenQueues(sourceQueueName, destinationQueueName) {
|
|
107
|
+
this.logger.info(`Transferring messages from ${sourceQueueName} to ${destinationQueueName} is being started`);
|
|
108
|
+
let messageCount = 0;
|
|
109
|
+
const channel = await this.connection.createChannel();
|
|
110
|
+
while (true) {
|
|
111
|
+
let message;
|
|
112
|
+
try {
|
|
113
|
+
const gotMessage = await channel.get(sourceQueueName, { noAck: true });
|
|
114
|
+
if (!gotMessage) break;
|
|
115
|
+
message = gotMessage;
|
|
116
|
+
messageCount += 1;
|
|
117
|
+
} catch (err) {
|
|
118
|
+
this.logger.error(`Error while getting messages from ${sourceQueueName}`, {
|
|
119
|
+
err,
|
|
120
|
+
messageCount
|
|
121
|
+
});
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
channel.sendToQueue(destinationQueueName, message.content, message.properties);
|
|
126
|
+
this.logger.debug(`Message ${messageCount} has been transferred from ${sourceQueueName} to ${destinationQueueName}`);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
this.logger.error(`Error while publishing messages to ${destinationQueueName}`, {
|
|
129
|
+
err,
|
|
130
|
+
messageCount
|
|
131
|
+
});
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
await channel.close();
|
|
136
|
+
this.logger.info(`Transferring messages from ${sourceQueueName} to ${destinationQueueName} has been finished`, { messageCount });
|
|
137
|
+
}
|
|
138
|
+
async deleteExchanges(exchangesOptions) {
|
|
139
|
+
const result = {};
|
|
140
|
+
for (const exchangeOptions of exchangesOptions) {
|
|
141
|
+
const { name: exchangeName } = exchangeOptions;
|
|
142
|
+
result[exchangeName] = await this.deleteExchange(exchangeName);
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
async deleteExchange(exchangeName) {
|
|
147
|
+
try {
|
|
148
|
+
const result = await this.channel?.deleteExchange(exchangeName);
|
|
149
|
+
this.logger.info(`Exchange ${exchangeName} has been deleted`);
|
|
150
|
+
return result;
|
|
151
|
+
} catch (err) {
|
|
152
|
+
this.logger.error(`Error while deleting an exchange`, {
|
|
153
|
+
exchangeName,
|
|
154
|
+
err
|
|
155
|
+
});
|
|
156
|
+
throw err;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async deleteQueues(queueNames) {
|
|
160
|
+
const result = {};
|
|
161
|
+
for (const queueName of queueNames) result[queueName] = await this.deleteQueue(queueName);
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
async deleteQueue(queueName) {
|
|
165
|
+
try {
|
|
166
|
+
const result = await this.channel?.deleteQueue(queueName);
|
|
167
|
+
this.logger.info(`Queue ${queueName} has been deleted`, {
|
|
168
|
+
queueName,
|
|
169
|
+
result
|
|
170
|
+
});
|
|
171
|
+
return result;
|
|
172
|
+
} catch (err) {
|
|
173
|
+
this.logger.error(`Error while deleting a queue`, {
|
|
174
|
+
queueName,
|
|
175
|
+
err
|
|
176
|
+
});
|
|
177
|
+
throw err;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async assertQueues(queueOptions) {
|
|
181
|
+
const result = {};
|
|
182
|
+
for (const queueOption of queueOptions) result[queueOption.name] = await this.assertQueue(queueOption);
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
async assertQueue(queueOptions) {
|
|
186
|
+
const { bindTo, declare, name: queueName, unbindFrom = [], type = QueueTypes.Quorum, options = this.defaultQueueOptions } = queueOptions;
|
|
187
|
+
const shouldDeclare = declare ?? this.declareOptions.assertQueues;
|
|
188
|
+
options.arguments = {
|
|
189
|
+
...options.arguments,
|
|
190
|
+
...type === QueueTypes.Quorum ? { [Arguments.queueType]: type } : {}
|
|
191
|
+
};
|
|
192
|
+
try {
|
|
193
|
+
if (shouldDeclare) {
|
|
194
|
+
const result = await this.channel?.assertQueue(queueName, options);
|
|
195
|
+
this.logger.info(`Queue ${queueName} has been declared`, {
|
|
196
|
+
queueOptions,
|
|
197
|
+
result
|
|
198
|
+
});
|
|
199
|
+
for (const bindOptions of bindTo) await this.bindQueueToExchange(queueName, bindOptions);
|
|
200
|
+
for (const unbindOption of unbindFrom) await this.unbindQueueFromExchange(queueName, unbindOption);
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
} catch (err) {
|
|
204
|
+
this.logger.error(`Error while assert queue`, {
|
|
205
|
+
queueName,
|
|
206
|
+
err
|
|
207
|
+
});
|
|
208
|
+
throw err;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async assertExchanges(exchangeOptions) {
|
|
212
|
+
const result = {};
|
|
213
|
+
for (const exchangeOption of exchangeOptions) result[exchangeOption.name] = await this.assertExchange(exchangeOption);
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
async assertExchange(exchangeOptions) {
|
|
217
|
+
const { name, delayed, declare, bindTo = [], type = this.defaultExchangeType, options = this.defaultExchangeOptions } = exchangeOptions;
|
|
218
|
+
options.arguments = {
|
|
219
|
+
...options.arguments,
|
|
220
|
+
...delayed ? { [Arguments.delayedType]: "topic" } : {}
|
|
221
|
+
};
|
|
222
|
+
const exchangeType = delayed ? "x-delayed-message" : type;
|
|
223
|
+
const shouldDeclare = declare ?? this.declareOptions.assertExchanges;
|
|
224
|
+
try {
|
|
225
|
+
if (shouldDeclare) {
|
|
226
|
+
const result = await this.channel?.assertExchange(name, exchangeType, options);
|
|
227
|
+
this.logger.info(`Exchange ${name} has been declared`, {
|
|
228
|
+
exchangeOptions,
|
|
229
|
+
result
|
|
230
|
+
});
|
|
231
|
+
await this.bindExchangeToExchanges(name, bindTo);
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
} catch (err) {
|
|
235
|
+
this.logger.error(`Error while assert exchange`, {
|
|
236
|
+
name,
|
|
237
|
+
err
|
|
238
|
+
});
|
|
239
|
+
throw err;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async unbindQueueFromExchanges(queueOptions) {
|
|
243
|
+
const { name: queueName, unbindFrom = [] } = queueOptions;
|
|
244
|
+
for (const unbindOption of unbindFrom) await this.unbindQueueFromExchange(queueName, unbindOption);
|
|
245
|
+
}
|
|
246
|
+
async bindQueueToExchange(queueName, bindOptions) {
|
|
247
|
+
const { bind, exchangeName, routingKey = constants_default.DEFAULT_ROUTING_KEY } = bindOptions;
|
|
248
|
+
const shouldBind = bind ?? this.declareOptions.assertQueues;
|
|
249
|
+
try {
|
|
250
|
+
if (shouldBind) {
|
|
251
|
+
const result = await this.channel?.bindQueue(queueName, exchangeName, routingKey);
|
|
252
|
+
this.logger.info(`Queue [${queueName}] has been bound with exchange [${exchangeName}] by routing key [${routingKey}]`);
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
} catch (err) {
|
|
256
|
+
this.logger.error(`Error while binding queue [${queueName}] to exchange [${exchangeName}] by routing key [${routingKey}]`, { err });
|
|
257
|
+
throw err;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async bindExchangeToExchanges(exchangeName, bindTo) {
|
|
261
|
+
for (const bindOption of bindTo) await this.bindExchangeToExchange(exchangeName, bindOption);
|
|
262
|
+
}
|
|
263
|
+
async bindExchangeToExchange(exchangeName, bindOptions) {
|
|
264
|
+
const { bind, exchangeName: relatedExchangeName, routingKey = constants_default.DEFAULT_ROUTING_KEY } = bindOptions;
|
|
265
|
+
const shouldBind = bind ?? this.declareOptions.assertExchanges;
|
|
266
|
+
try {
|
|
267
|
+
if (shouldBind) {
|
|
268
|
+
const result = await this.channel?.bindExchange(exchangeName, relatedExchangeName, routingKey);
|
|
269
|
+
this.logger.info(`Exchange [${exchangeName}] has been bound with exchange [${relatedExchangeName}] by routing key [${routingKey}]`);
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
} catch (err) {
|
|
273
|
+
this.logger.error(`Error while binding exchange [${exchangeName}] to exchange [${relatedExchangeName}] by routing key [${routingKey}]`, { err });
|
|
274
|
+
throw err;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
async unbindQueueFromExchange(queueName, unbindOptions) {
|
|
278
|
+
const { unbind, exchangeName, routingKey = constants_default.DEFAULT_ROUTING_KEY } = unbindOptions;
|
|
279
|
+
try {
|
|
280
|
+
if (unbind) {
|
|
281
|
+
const result = await this.channel?.unbindQueue(queueName, exchangeName, routingKey);
|
|
282
|
+
this.logger.info(`Queue [${queueName}] has been unbound from exchange [${exchangeName}] by routing key [${routingKey}]`);
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
} catch (err) {
|
|
286
|
+
this.logger.error(`Error while unbinding queue [${queueName}] from exchange [${exchangeName}] by routing key [${routingKey}]`, { err });
|
|
287
|
+
throw err;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async disconnect() {
|
|
291
|
+
await this.channel?.close();
|
|
292
|
+
this.connection.removeAllListeners(AmqpConnectionEventNames.Ready);
|
|
293
|
+
await this.connection.closeConnection();
|
|
294
|
+
}
|
|
295
|
+
async initChannel() {
|
|
296
|
+
this.channel = await this.connection.createChannel(this.channelName);
|
|
297
|
+
}
|
|
298
|
+
async readConfig(declarationConfigPath) {
|
|
299
|
+
const data = await readFile(declarationConfigPath, { encoding: "utf8" });
|
|
300
|
+
return JSON.parse(data);
|
|
301
|
+
}
|
|
302
|
+
async assertTemporaryQueue(queueOptions) {
|
|
303
|
+
const tempQueueOptions = this.prepareTemporaryQueueOptions(queueOptions);
|
|
304
|
+
await this.assertQueue(tempQueueOptions);
|
|
305
|
+
return tempQueueOptions;
|
|
306
|
+
}
|
|
307
|
+
async assertAlternateExchanges(queueOptions, exchangesOptions) {
|
|
308
|
+
const alternateExchangesOptions = this.prepareAlternateExchangesOptions(queueOptions, exchangesOptions);
|
|
309
|
+
await this.assertExchanges(Object.values(alternateExchangesOptions));
|
|
310
|
+
return alternateExchangesOptions;
|
|
311
|
+
}
|
|
312
|
+
async assertAlternateQueue(queueOptions, alternateExchangesOptions) {
|
|
313
|
+
const alternateQueueOptions = this.prepareAlternateQueueOptions(queueOptions, alternateExchangesOptions);
|
|
314
|
+
await this.assertQueue(alternateQueueOptions);
|
|
315
|
+
return alternateQueueOptions;
|
|
316
|
+
}
|
|
317
|
+
prepareRedeclareQueueOptions(queueOptions, redeclareQueueOptions) {
|
|
318
|
+
return {
|
|
319
|
+
...queueOptions,
|
|
320
|
+
...redeclareQueueOptions
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
prepareTemporaryQueueOptions(queueOptions) {
|
|
324
|
+
return {
|
|
325
|
+
...queueOptions,
|
|
326
|
+
name: `${queueOptions.name}Temporary`
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
prepareAlternateExchangesOptions(queueOptions, exchangesOptions) {
|
|
330
|
+
const result = {};
|
|
331
|
+
if (exchangesOptions.length === 0) return result;
|
|
332
|
+
const exchangesOptionsMap = new Map(exchangesOptions.map((exchangeOptions) => [exchangeOptions.name, exchangeOptions]));
|
|
333
|
+
for (const bindOptions of queueOptions.bindTo) {
|
|
334
|
+
const { exchangeName, bind } = bindOptions;
|
|
335
|
+
if (!bind) continue;
|
|
336
|
+
const exchangeOptions = exchangesOptionsMap.get(exchangeName);
|
|
337
|
+
if (!exchangeOptions) throw new Error(`Alternate exchange options could not be defined for unknown exchange [${exchangeName}]`);
|
|
338
|
+
result[exchangeName] = this.prepareAlternateExchangeOptions(exchangeOptions);
|
|
339
|
+
}
|
|
340
|
+
return result;
|
|
341
|
+
}
|
|
342
|
+
prepareAlternateExchangeOptions(exchangeOptions) {
|
|
343
|
+
const { name: exchangeName } = exchangeOptions;
|
|
344
|
+
return {
|
|
345
|
+
...exchangeOptions,
|
|
346
|
+
declare: true,
|
|
347
|
+
name: `${exchangeName}${AmqpAsserter.PrefixAlternate}`
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
prepareAlternateQueueOptions(queueOptions, alternateExchangesOptions) {
|
|
351
|
+
const { name: queueName, bindTo = [] } = queueOptions;
|
|
352
|
+
return {
|
|
353
|
+
...queueOptions,
|
|
354
|
+
name: `${queueName}${AmqpAsserter.PrefixAlternate}`,
|
|
355
|
+
bindTo: this.prepareAlternateBindToQueueOption(bindTo, alternateExchangesOptions)
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
prepareAlternateBindToQueueOption(bindTo, alternateExchangesOptions) {
|
|
359
|
+
return bindTo.filter(({ exchangeName }) => exchangeName in alternateExchangesOptions).map(({ exchangeName, routingKey }) => {
|
|
360
|
+
const { name: alternateExchangeName } = alternateExchangesOptions[exchangeName];
|
|
361
|
+
return {
|
|
362
|
+
bind: true,
|
|
363
|
+
routingKey,
|
|
364
|
+
exchangeName: alternateExchangeName
|
|
365
|
+
};
|
|
366
|
+
});
|
|
367
|
+
}
|
|
4
368
|
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const promises_1 = require("node:fs/promises");
|
|
8
|
-
const constants_1 = __importDefault(require("../../constants"));
|
|
9
|
-
const interfaces_1 = require("../../interfaces");
|
|
10
|
-
const messageBrokerServiceConfig_1 = require("../../interfaces/messageBrokerServiceConfig");
|
|
11
|
-
class AmqpAsserter {
|
|
12
|
-
connection;
|
|
13
|
-
logger;
|
|
14
|
-
declareOptions;
|
|
15
|
-
static PrefixAlternate = 'Alternate';
|
|
16
|
-
defaultExchangeType = messageBrokerServiceConfig_1.ExchangeType.Topic;
|
|
17
|
-
defaultQueueOptions = { durable: true };
|
|
18
|
-
defaultExchangeOptions = {
|
|
19
|
-
durable: true,
|
|
20
|
-
autoDelete: false,
|
|
21
|
-
};
|
|
22
|
-
defaultDeclareOptions = {
|
|
23
|
-
assertQueues: true,
|
|
24
|
-
assertExchanges: true,
|
|
25
|
-
};
|
|
26
|
-
channel;
|
|
27
|
-
channelName = 'asserterChannel';
|
|
28
|
-
constructor(connection, logger, declareOptions = {}) {
|
|
29
|
-
this.connection = connection;
|
|
30
|
-
this.logger = logger;
|
|
31
|
-
this.declareOptions = declareOptions;
|
|
32
|
-
declareOptions.assertQueues ??= this.defaultDeclareOptions.assertQueues;
|
|
33
|
-
declareOptions.assertExchanges ??= this.defaultDeclareOptions.assertExchanges;
|
|
34
|
-
}
|
|
35
|
-
async init(exchangesOptions = [], queuesOptions = []) {
|
|
36
|
-
if (!this.channel) {
|
|
37
|
-
await this.initChannel();
|
|
38
|
-
this.connection.on(interfaces_1.AmqpConnectionEventNames.Ready, async () => {
|
|
39
|
-
// in case if reconnect happened
|
|
40
|
-
await this.initChannel();
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
await this.assertExchanges(exchangesOptions);
|
|
44
|
-
await this.declareQueues(queuesOptions, exchangesOptions);
|
|
45
|
-
}
|
|
46
|
-
async declareQueuesByJSON(declarationConfigPath) {
|
|
47
|
-
const { exchangesOptions, queuesOptions } = await this.readConfig(declarationConfigPath);
|
|
48
|
-
await this.declareQueues(queuesOptions, exchangesOptions);
|
|
49
|
-
}
|
|
50
|
-
async declareQueues(queuesOptions = [], exchangesOptions = []) {
|
|
51
|
-
for await (const queueOptions of queuesOptions) {
|
|
52
|
-
const { name: queueName, redeclareOptions: { redeclare } = {} } = queueOptions;
|
|
53
|
-
if (redeclare) {
|
|
54
|
-
try {
|
|
55
|
-
await this.redeclareQueue(queueOptions, exchangesOptions);
|
|
56
|
-
}
|
|
57
|
-
catch (err) {
|
|
58
|
-
this.logger.error(`Error while redeclaring queue ${queueName}`, { err });
|
|
59
|
-
throw err;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
await this.assertQueue(queueOptions);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
async redeclareQueue(queueOptions, exchangesOptions) {
|
|
68
|
-
const { bindTo = [], redeclareOptions = {} } = queueOptions;
|
|
69
|
-
const { redeclare } = redeclareOptions;
|
|
70
|
-
if (!redeclare) {
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
// prepare redeclare queue options
|
|
74
|
-
const redeclareQueueOptions = this.prepareRedeclareQueueOptions(queueOptions, redeclareOptions);
|
|
75
|
-
const { name: queueName } = redeclareQueueOptions;
|
|
76
|
-
this.logger.info(`Queue ${queueName} is being to be redeclared`, { options: redeclareQueueOptions });
|
|
77
|
-
// assert alternate exchanges
|
|
78
|
-
const alternateExchangesOptions = await this.assertAlternateExchanges(redeclareQueueOptions, exchangesOptions);
|
|
79
|
-
// assert alternate queue
|
|
80
|
-
const { name: alternateQueueName } = await this.assertAlternateQueue(redeclareQueueOptions, alternateExchangesOptions);
|
|
81
|
-
// unbind old queue
|
|
82
|
-
await this.unbindQueueFromExchanges({
|
|
83
|
-
bindTo: [],
|
|
84
|
-
name: queueName,
|
|
85
|
-
unbindFrom: bindTo.map(({ exchangeName, routingKey }) => ({
|
|
86
|
-
routingKey,
|
|
87
|
-
exchangeName,
|
|
88
|
-
unbind: true,
|
|
89
|
-
})),
|
|
90
|
-
});
|
|
91
|
-
// assert temporary queue
|
|
92
|
-
const { name: tempQueueName, bindTo: tempBindTo } = await this.assertTemporaryQueue(redeclareQueueOptions);
|
|
93
|
-
// transfer messages from old queue to temporary queue
|
|
94
|
-
await this.transferMessageBetweenQueues(queueName, tempQueueName);
|
|
95
|
-
try {
|
|
96
|
-
// delete old queue
|
|
97
|
-
await this.deleteQueue(queueName);
|
|
98
|
-
}
|
|
99
|
-
catch (err) {
|
|
100
|
-
if (!(err instanceof Error)) {
|
|
101
|
-
throw err;
|
|
102
|
-
}
|
|
103
|
-
if (err.message.includes('NOT_FOUND - no queue')) {
|
|
104
|
-
await this.deleteQueues([alternateQueueName, tempQueueName]);
|
|
105
|
-
await this.deleteExchanges(Object.values(alternateExchangesOptions));
|
|
106
|
-
}
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
// assert new queue
|
|
110
|
-
await this.assertQueue(redeclareQueueOptions);
|
|
111
|
-
// unbind temp queue
|
|
112
|
-
await this.unbindQueueFromExchanges({
|
|
113
|
-
bindTo: [],
|
|
114
|
-
name: tempQueueName,
|
|
115
|
-
unbindFrom: tempBindTo.map(({ exchangeName, routingKey }) => ({
|
|
116
|
-
routingKey,
|
|
117
|
-
exchangeName,
|
|
118
|
-
unbind: true,
|
|
119
|
-
})),
|
|
120
|
-
});
|
|
121
|
-
// transfer messages from temporary queue to new queue
|
|
122
|
-
await this.transferMessageBetweenQueues(tempQueueName, queueName);
|
|
123
|
-
// transfer messages from alternate queue to new queue
|
|
124
|
-
await this.transferMessageBetweenQueues(alternateQueueName, queueName);
|
|
125
|
-
// delete temporary queue
|
|
126
|
-
await this.deleteQueue(tempQueueName);
|
|
127
|
-
// delete alternate queue
|
|
128
|
-
await this.deleteQueue(alternateQueueName);
|
|
129
|
-
// delete alternate exchanges
|
|
130
|
-
await this.deleteExchanges(Object.values(alternateExchangesOptions));
|
|
131
|
-
this.logger.info(`Queue ${queueName} has been redeclared successfully`);
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
async transferMessageBetweenQueues(sourceQueueName, destinationQueueName) {
|
|
135
|
-
this.logger.info(`Transferring messages from ${sourceQueueName} to ${destinationQueueName} is being started`);
|
|
136
|
-
let messageCount = 0;
|
|
137
|
-
const channel = await this.connection.createChannel();
|
|
138
|
-
while (true) {
|
|
139
|
-
let message;
|
|
140
|
-
try {
|
|
141
|
-
const gotMessage = await channel.get(sourceQueueName, { noAck: true });
|
|
142
|
-
if (!gotMessage) {
|
|
143
|
-
break;
|
|
144
|
-
}
|
|
145
|
-
message = gotMessage;
|
|
146
|
-
messageCount += 1;
|
|
147
|
-
}
|
|
148
|
-
catch (err) {
|
|
149
|
-
this.logger.error(`Error while getting messages from ${sourceQueueName}`, { err, messageCount });
|
|
150
|
-
throw err;
|
|
151
|
-
}
|
|
152
|
-
try {
|
|
153
|
-
channel.sendToQueue(destinationQueueName, message.content, message.properties);
|
|
154
|
-
this.logger.debug(`Message ${messageCount} has been transferred from ${sourceQueueName} to ${destinationQueueName}`);
|
|
155
|
-
}
|
|
156
|
-
catch (err) {
|
|
157
|
-
this.logger.error(`Error while publishing messages to ${destinationQueueName}`, { err, messageCount });
|
|
158
|
-
throw err;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
await channel.close();
|
|
162
|
-
this.logger.info(`Transferring messages from ${sourceQueueName} to ${destinationQueueName} has been finished`, {
|
|
163
|
-
messageCount,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
async deleteExchanges(exchangesOptions) {
|
|
167
|
-
const result = {};
|
|
168
|
-
for await (const exchangeOptions of exchangesOptions) {
|
|
169
|
-
const { name: exchangeName } = exchangeOptions;
|
|
170
|
-
result[exchangeName] = await this.deleteExchange(exchangeName);
|
|
171
|
-
}
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
|
-
async deleteExchange(exchangeName) {
|
|
175
|
-
try {
|
|
176
|
-
const result = await this.channel?.deleteExchange(exchangeName);
|
|
177
|
-
this.logger.info(`Exchange ${exchangeName} has been deleted`);
|
|
178
|
-
return result;
|
|
179
|
-
}
|
|
180
|
-
catch (err) {
|
|
181
|
-
this.logger.error(`Error while deleting an exchange`, { exchangeName, err });
|
|
182
|
-
throw err;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
async deleteQueues(queueNames) {
|
|
186
|
-
const result = {};
|
|
187
|
-
for (const queueName of queueNames) {
|
|
188
|
-
result[queueName] = await this.deleteQueue(queueName);
|
|
189
|
-
}
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
async deleteQueue(queueName) {
|
|
193
|
-
try {
|
|
194
|
-
const result = await this.channel?.deleteQueue(queueName);
|
|
195
|
-
this.logger.info(`Queue ${queueName} has been deleted`, { queueName, result });
|
|
196
|
-
return result;
|
|
197
|
-
}
|
|
198
|
-
catch (err) {
|
|
199
|
-
this.logger.error(`Error while deleting a queue`, { queueName, err });
|
|
200
|
-
throw err;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
async assertQueues(queueOptions) {
|
|
204
|
-
const result = {};
|
|
205
|
-
for await (const queueOption of queueOptions) {
|
|
206
|
-
result[queueOption.name] = await this.assertQueue(queueOption);
|
|
207
|
-
}
|
|
208
|
-
return result;
|
|
209
|
-
}
|
|
210
|
-
async assertQueue(queueOptions) {
|
|
211
|
-
const { bindTo, declare, name: queueName, unbindFrom = [], type = messageBrokerServiceConfig_1.QueueTypes.Quorum, options = this.defaultQueueOptions, } = queueOptions;
|
|
212
|
-
const shouldDeclare = declare ?? this.declareOptions.assertQueues;
|
|
213
|
-
options.arguments = {
|
|
214
|
-
...options.arguments,
|
|
215
|
-
...(type === messageBrokerServiceConfig_1.QueueTypes.Quorum
|
|
216
|
-
? {
|
|
217
|
-
[interfaces_1.Arguments.queueType]: type,
|
|
218
|
-
}
|
|
219
|
-
: {}),
|
|
220
|
-
};
|
|
221
|
-
try {
|
|
222
|
-
if (shouldDeclare) {
|
|
223
|
-
const result = await this.channel?.assertQueue(queueName, options);
|
|
224
|
-
this.logger.info(`Queue ${queueName} has been declared`, { queueOptions, result });
|
|
225
|
-
for await (const bindOptions of bindTo) {
|
|
226
|
-
await this.bindQueueToExchange(queueName, bindOptions);
|
|
227
|
-
}
|
|
228
|
-
for await (const unbindOption of unbindFrom) {
|
|
229
|
-
await this.unbindQueueFromExchange(queueName, unbindOption);
|
|
230
|
-
}
|
|
231
|
-
return result;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
catch (err) {
|
|
235
|
-
this.logger.error(`Error while assert queue`, { queueName, err });
|
|
236
|
-
throw err;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
async assertExchanges(exchangeOptions) {
|
|
240
|
-
const result = {};
|
|
241
|
-
for await (const exchangeOption of exchangeOptions) {
|
|
242
|
-
result[exchangeOption.name] = await this.assertExchange(exchangeOption);
|
|
243
|
-
}
|
|
244
|
-
return result;
|
|
245
|
-
}
|
|
246
|
-
async assertExchange(exchangeOptions) {
|
|
247
|
-
const { name, delayed, declare, bindTo = [], type = this.defaultExchangeType, options = this.defaultExchangeOptions, } = exchangeOptions;
|
|
248
|
-
options.arguments = {
|
|
249
|
-
...options.arguments,
|
|
250
|
-
...(delayed ? { [interfaces_1.Arguments.delayedType]: messageBrokerServiceConfig_1.ExchangeType.Topic } : {}),
|
|
251
|
-
};
|
|
252
|
-
const exchangeType = delayed ? messageBrokerServiceConfig_1.ExchangeType.XDelayedMessage : type;
|
|
253
|
-
const shouldDeclare = declare ?? this.declareOptions.assertExchanges;
|
|
254
|
-
try {
|
|
255
|
-
if (shouldDeclare) {
|
|
256
|
-
const result = await this.channel?.assertExchange(name, exchangeType, options);
|
|
257
|
-
this.logger.info(`Exchange ${name} has been declared`, { exchangeOptions, result });
|
|
258
|
-
await this.bindExchangeToExchanges(name, bindTo);
|
|
259
|
-
return result;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
catch (err) {
|
|
263
|
-
this.logger.error(`Error while assert exchange`, { name, err });
|
|
264
|
-
throw err;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
async unbindQueueFromExchanges(queueOptions) {
|
|
268
|
-
const { name: queueName, unbindFrom = [] } = queueOptions;
|
|
269
|
-
for await (const unbindOption of unbindFrom) {
|
|
270
|
-
await this.unbindQueueFromExchange(queueName, unbindOption);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
async bindQueueToExchange(queueName, bindOptions) {
|
|
274
|
-
const { bind, exchangeName, routingKey = constants_1.default.DEFAULT_ROUTING_KEY } = bindOptions;
|
|
275
|
-
const shouldBind = bind ?? this.declareOptions.assertQueues;
|
|
276
|
-
try {
|
|
277
|
-
if (shouldBind) {
|
|
278
|
-
const result = await this.channel?.bindQueue(queueName, exchangeName, routingKey);
|
|
279
|
-
this.logger.info(`Queue [${queueName}] has been bound with exchange [${exchangeName}] by routing key [${routingKey}]`);
|
|
280
|
-
return result;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
catch (err) {
|
|
284
|
-
this.logger.error(`Error while binding queue [${queueName}] to exchange [${exchangeName}] by routing key [${routingKey}]`, {
|
|
285
|
-
err,
|
|
286
|
-
});
|
|
287
|
-
throw err;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
async bindExchangeToExchanges(exchangeName, bindTo) {
|
|
291
|
-
for await (const bindOption of bindTo) {
|
|
292
|
-
await this.bindExchangeToExchange(exchangeName, bindOption);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
async bindExchangeToExchange(exchangeName, bindOptions) {
|
|
296
|
-
const { bind, exchangeName: relatedExchangeName, routingKey = constants_1.default.DEFAULT_ROUTING_KEY } = bindOptions;
|
|
297
|
-
const shouldBind = bind ?? this.declareOptions.assertExchanges;
|
|
298
|
-
try {
|
|
299
|
-
if (shouldBind) {
|
|
300
|
-
const result = await this.channel?.bindExchange(exchangeName, relatedExchangeName, routingKey);
|
|
301
|
-
this.logger.info(`Exchange [${exchangeName}] has been bound with exchange [${relatedExchangeName}] by routing key [${routingKey}]`);
|
|
302
|
-
return result;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
catch (err) {
|
|
306
|
-
this.logger.error(`Error while binding exchange [${exchangeName}] to exchange [${relatedExchangeName}] by routing key [${routingKey}]`, {
|
|
307
|
-
err,
|
|
308
|
-
});
|
|
309
|
-
throw err;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
async unbindQueueFromExchange(queueName, unbindOptions) {
|
|
313
|
-
const { unbind, exchangeName, routingKey = constants_1.default.DEFAULT_ROUTING_KEY } = unbindOptions;
|
|
314
|
-
try {
|
|
315
|
-
if (unbind) {
|
|
316
|
-
const result = await this.channel?.unbindQueue(queueName, exchangeName, routingKey);
|
|
317
|
-
this.logger.info(`Queue [${queueName}] has been unbound from exchange [${exchangeName}] by routing key [${routingKey}]`);
|
|
318
|
-
return result;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
catch (err) {
|
|
322
|
-
this.logger.error(`Error while unbinding queue [${queueName}] from exchange [${exchangeName}] by routing key [${routingKey}]`, {
|
|
323
|
-
err,
|
|
324
|
-
});
|
|
325
|
-
throw err;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
async disconnect() {
|
|
329
|
-
await this.channel?.close();
|
|
330
|
-
this.connection.removeAllListeners(interfaces_1.AmqpConnectionEventNames.Ready);
|
|
331
|
-
await this.connection.closeConnection();
|
|
332
|
-
}
|
|
333
|
-
async initChannel() {
|
|
334
|
-
this.channel = await this.connection.createChannel(this.channelName);
|
|
335
|
-
}
|
|
336
|
-
async readConfig(declarationConfigPath) {
|
|
337
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
338
|
-
const data = await (0, promises_1.readFile)(declarationConfigPath, { encoding: 'utf8' }); // nosemgrep: eslint.detect-non-literal-fs-filename
|
|
339
|
-
return JSON.parse(data);
|
|
340
|
-
}
|
|
341
|
-
async assertTemporaryQueue(queueOptions) {
|
|
342
|
-
const tempQueueOptions = this.prepareTemporaryQueueOptions(queueOptions);
|
|
343
|
-
await this.assertQueue(tempQueueOptions);
|
|
344
|
-
return tempQueueOptions;
|
|
345
|
-
}
|
|
346
|
-
async assertAlternateExchanges(queueOptions, exchangesOptions) {
|
|
347
|
-
const alternateExchangesOptions = this.prepareAlternateExchangesOptions(queueOptions, exchangesOptions);
|
|
348
|
-
await this.assertExchanges(Object.values(alternateExchangesOptions));
|
|
349
|
-
return alternateExchangesOptions;
|
|
350
|
-
}
|
|
351
|
-
async assertAlternateQueue(queueOptions, alternateExchangesOptions) {
|
|
352
|
-
const alternateQueueOptions = this.prepareAlternateQueueOptions(queueOptions, alternateExchangesOptions);
|
|
353
|
-
await this.assertQueue(alternateQueueOptions);
|
|
354
|
-
return alternateQueueOptions;
|
|
355
|
-
}
|
|
356
|
-
prepareRedeclareQueueOptions(queueOptions, redeclareQueueOptions) {
|
|
357
|
-
return {
|
|
358
|
-
...queueOptions,
|
|
359
|
-
...redeclareQueueOptions,
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
prepareTemporaryQueueOptions(queueOptions) {
|
|
363
|
-
return {
|
|
364
|
-
...queueOptions,
|
|
365
|
-
name: `${queueOptions.name}Temporary`,
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
prepareAlternateExchangesOptions(queueOptions, exchangesOptions) {
|
|
369
|
-
const result = {};
|
|
370
|
-
if (exchangesOptions.length === 0) {
|
|
371
|
-
return result;
|
|
372
|
-
}
|
|
373
|
-
const exchangesOptionsMap = new Map(exchangesOptions.map((exchangeOptions) => [exchangeOptions.name, exchangeOptions]));
|
|
374
|
-
for (const bindOptions of queueOptions.bindTo) {
|
|
375
|
-
const { exchangeName, bind } = bindOptions;
|
|
376
|
-
if (!bind) {
|
|
377
|
-
continue;
|
|
378
|
-
}
|
|
379
|
-
const exchangeOptions = exchangesOptionsMap.get(exchangeName);
|
|
380
|
-
if (!exchangeOptions) {
|
|
381
|
-
throw new Error(`Alternate exchange options could not be defined for unknown exchange [${exchangeName}]`);
|
|
382
|
-
}
|
|
383
|
-
result[exchangeName] = this.prepareAlternateExchangeOptions(exchangeOptions);
|
|
384
|
-
}
|
|
385
|
-
return result;
|
|
386
|
-
}
|
|
387
|
-
prepareAlternateExchangeOptions(exchangeOptions) {
|
|
388
|
-
const { name: exchangeName } = exchangeOptions;
|
|
389
|
-
return {
|
|
390
|
-
...exchangeOptions,
|
|
391
|
-
declare: true,
|
|
392
|
-
name: `${exchangeName}${AmqpAsserter.PrefixAlternate}`,
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
prepareAlternateQueueOptions(queueOptions, alternateExchangesOptions) {
|
|
396
|
-
const { name: queueName, bindTo = [] } = queueOptions;
|
|
397
|
-
return {
|
|
398
|
-
...queueOptions,
|
|
399
|
-
name: `${queueName}${AmqpAsserter.PrefixAlternate}`,
|
|
400
|
-
bindTo: this.prepareAlternateBindToQueueOption(bindTo, alternateExchangesOptions),
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
prepareAlternateBindToQueueOption(bindTo, alternateExchangesOptions) {
|
|
404
|
-
return bindTo
|
|
405
|
-
.filter(({ exchangeName }) => exchangeName in alternateExchangesOptions)
|
|
406
|
-
.map(({ exchangeName, routingKey }) => {
|
|
407
|
-
const { name: alternateExchangeName } = alternateExchangesOptions[exchangeName];
|
|
408
|
-
return {
|
|
409
|
-
bind: true,
|
|
410
|
-
routingKey,
|
|
411
|
-
exchangeName: alternateExchangeName,
|
|
412
|
-
};
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
exports.AmqpAsserter = AmqpAsserter;
|
|
417
|
-
//# sourceMappingURL=amqpAsserter.js.map
|
|
369
|
+
//#endregion
|
|
370
|
+
export { AmqpAsserter };
|