@azteam/rabbitmq-async 1.0.146 → 1.0.147

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azteam/rabbitmq-async",
3
- "version": "1.0.146",
3
+ "version": "1.0.147",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "module": "./src/index.js",
@@ -0,0 +1,34 @@
1
+ import RabbitMQAsync from './RabbitMQAsync';
2
+
3
+ class Provider {
4
+ constructor(configs = []) {
5
+ this.connections = {};
6
+ this.configs = {};
7
+ if (Array.isArray(configs)) {
8
+ configs.map((config) => {
9
+ this.configs[config.name] = config;
10
+ return true;
11
+ });
12
+ } else {
13
+ this.configs.main = configs;
14
+ }
15
+ }
16
+
17
+ getConnection(name = 'main') {
18
+ if (!this.connections[name]) {
19
+ this.connections[name] = new RabbitMQAsync(this.configs[name]);
20
+ }
21
+ return this.connections[name];
22
+ }
23
+
24
+ async waitAllConnection() {
25
+ await Promise.all(
26
+ Object.keys(this.configs).map((keyConfig) => {
27
+ const connection = this.getConnection(keyConfig);
28
+ return connection.waitConnection();
29
+ })
30
+ );
31
+ }
32
+ }
33
+
34
+ export default Provider;
@@ -0,0 +1,220 @@
1
+ import amqp from 'amqplib';
2
+ import {timeout} from '@azteam/util';
3
+ import _ from 'lodash';
4
+
5
+ class RabbitMQAsync {
6
+ constructor(config) {
7
+ this.connected = false;
8
+ this.username = config.username;
9
+ this.password = config.password;
10
+ this.host = config.host;
11
+ this.prefix = config.prefix;
12
+ this.connect();
13
+ }
14
+
15
+ async waitConnection(n = 10) {
16
+ for (let i = 0; !this.connected || i < n; i += 1) {
17
+ await timeout(1000);
18
+ }
19
+ if (!this.connected) {
20
+ throw new Error('Rabbit not connected');
21
+ }
22
+ }
23
+
24
+ async connect() {
25
+ this._alert('connecting', 'MQ connecting...');
26
+ const opt = {credentials: amqp.credentials.plain(this.username, this.password)};
27
+ try {
28
+ this.client = await amqp.connect(`amqp://${this.host}`, opt);
29
+ this.connected = true;
30
+ this._alert('connect', 'MQ connected');
31
+
32
+ this.client.on('error', (err) => {
33
+ this.connected = false;
34
+ this._alert('error', `MQ Error${err}`);
35
+ this.reconnect();
36
+ });
37
+
38
+ this.client.on('close', () => {
39
+ this.connected = false;
40
+ this._alert('close', 'MQ closed');
41
+ this.reconnect();
42
+ });
43
+ } catch (err) {
44
+ this.connected = false;
45
+ this._alert('error', `MQ connect${err}`);
46
+ await this.reconnect();
47
+ }
48
+ }
49
+
50
+ async reconnect() {
51
+ this._alert('reconnect', 'MQ try reconnect...');
52
+ await timeout(5000);
53
+ await this.connect();
54
+ }
55
+
56
+ close() {
57
+ this.connected = false;
58
+ this.client.close();
59
+ }
60
+
61
+ parsePrefix(name) {
62
+ if (this.prefix) {
63
+ return `${this.prefix}:${name}`;
64
+ }
65
+ return name;
66
+ }
67
+
68
+ async send(queueName, msg = {}, force = true) {
69
+ const prefixQueueName = this.parsePrefix(queueName);
70
+
71
+ if (this.connected) {
72
+ let channel;
73
+ try {
74
+ channel = await this.client.createChannel();
75
+ const queueInfo = await channel.assertQueue(prefixQueueName, {
76
+ durable: true,
77
+ });
78
+
79
+ if (force || queueInfo.messageCount === 0) {
80
+ await channel.sendToQueue(prefixQueueName, Buffer.from(JSON.stringify(msg)), {
81
+ persistent: true,
82
+ });
83
+ }
84
+
85
+ return true;
86
+ } catch (err) {
87
+ await timeout(2000);
88
+ return this.send(queueName, msg);
89
+ } finally {
90
+ try {
91
+ await channel.close();
92
+ } catch (err) {}
93
+ }
94
+ } else {
95
+ await timeout(2000);
96
+ return this.send(queueName, msg);
97
+ }
98
+ }
99
+
100
+ async getInfo(queueName) {
101
+ const prefixQueueName = this.parsePrefix(queueName);
102
+
103
+ if (this.connected) {
104
+ let channel;
105
+ try {
106
+ channel = await this.client.createChannel();
107
+ return await channel.assertQueue(prefixQueueName, {
108
+ durable: true,
109
+ });
110
+ } catch (err) {
111
+ return this.getInfo(queueName);
112
+ } finally {
113
+ try {
114
+ await channel.close();
115
+ } catch (err) {}
116
+ }
117
+ } else {
118
+ return this.getInfo(queueName);
119
+ }
120
+ }
121
+
122
+ async receiving(queueName, cb, callbackError = null) {
123
+ const prefixQueueName = this.parsePrefix(queueName);
124
+
125
+ if (this.connected) {
126
+ let channel;
127
+ try {
128
+ channel = await this.client.createChannel();
129
+
130
+ await channel.assertQueue(prefixQueueName, {
131
+ durable: true,
132
+ });
133
+
134
+ await channel.prefetch(1);
135
+
136
+ const messageQueue = this;
137
+
138
+ await new Promise((resolve, reject) => {
139
+ channel.consume(prefixQueueName, async function (msg) {
140
+ if (msg) {
141
+ const data = JSON.parse(msg.content.toString());
142
+
143
+ if (data) {
144
+ try {
145
+ if (msg.fields.redelivered) {
146
+ if (!data.retry) {
147
+ data.retry = 0;
148
+ }
149
+ data.retry += 1;
150
+
151
+ if (data.retry < 5) {
152
+ await messageQueue.send(queueName, data);
153
+ } else {
154
+ await messageQueue.send(messageQueue.parsePrefix('RETRY'), {
155
+ queueName,
156
+ data,
157
+ retry_time: new Date(),
158
+ });
159
+ }
160
+ await channel.ack(msg);
161
+ } else {
162
+ try {
163
+ await cb(data);
164
+ await channel.ack(msg);
165
+ } catch (err) {
166
+ const errString = err.toString();
167
+
168
+ if (_.some(['IllegalOperationError: Channel closed'], (el) => _.includes(errString, el))) {
169
+ reject(new Error(errString));
170
+ } else {
171
+ if (callbackError) {
172
+ callbackError(prefixQueueName, err);
173
+ }
174
+ if (data.noRetry) {
175
+ await channel.ack(msg);
176
+ } else {
177
+ await channel.nack(msg);
178
+ }
179
+ }
180
+ }
181
+ }
182
+ } catch (err) {
183
+ reject(err);
184
+ }
185
+ } else {
186
+ channel.ack(msg);
187
+ }
188
+ } else {
189
+ reject(new Error('msg null'));
190
+ }
191
+ });
192
+ });
193
+ } catch (err) {
194
+ try {
195
+ await channel.close();
196
+ } catch (err2) {}
197
+
198
+ await timeout(5000);
199
+ return this.receiving(queueName, cb, callbackError);
200
+ }
201
+ } else {
202
+ await timeout(5000);
203
+ return this.receiving(queueName, cb, callbackError);
204
+ }
205
+ }
206
+
207
+ setAlertCallback(callback) {
208
+ this.alertCallback = callback;
209
+ }
210
+
211
+ _alert(status, msg) {
212
+ if (typeof this.alertCallback === 'function') {
213
+ this.alertCallback(status, msg);
214
+ } else {
215
+ console.info(status, msg);
216
+ }
217
+ }
218
+ }
219
+
220
+ export default RabbitMQAsync;
package/src/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import Provider from './Provider';
2
+ import RabbitMQAsync from './RabbitMQAsync';
3
+
4
+ export {RabbitMQAsync, Provider as RabbitMQProvider};