rascal 13.1.1 → 14.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/.husky/pre-commit +1 -1
- package/.prettierrc.json +4 -0
- package/CHANGELOG.md +213 -1
- package/README.md +597 -381
- package/examples/advanced/cluster.js +8 -8
- package/examples/advanced/config.js +121 -123
- package/examples/advanced/handlers/deleteUser.js +16 -17
- package/examples/advanced/handlers/saveUser.js +32 -33
- package/examples/advanced/index.js +85 -80
- package/examples/busy-publisher/config.js +19 -22
- package/examples/busy-publisher/index.js +11 -12
- package/examples/default-exchange/config.js +13 -13
- package/examples/default-exchange/index.js +22 -18
- package/examples/mocha/config.js +13 -15
- package/examples/mocha/test.js +34 -35
- package/examples/promises/config.js +15 -17
- package/examples/promises/index.js +14 -12
- package/examples/simple/config.js +21 -23
- package/examples/simple/index.js +20 -22
- package/index.js +1 -1
- package/lib/amqp/Broker.js +105 -82
- package/lib/amqp/BrokerAsPromised.js +40 -28
- package/lib/amqp/Publication.js +15 -14
- package/lib/amqp/PublicationSession.js +6 -7
- package/lib/amqp/SubscriberError.js +159 -124
- package/lib/amqp/SubscriberSession.js +87 -68
- package/lib/amqp/SubscriberSessionAsPromised.js +1 -3
- package/lib/amqp/Subscription.js +25 -24
- package/lib/amqp/Vhost.js +93 -67
- package/lib/amqp/tasks/applyBindings.js +9 -6
- package/lib/amqp/tasks/assertExchanges.js +9 -5
- package/lib/amqp/tasks/assertQueues.js +9 -5
- package/lib/amqp/tasks/assertVhost.js +17 -13
- package/lib/amqp/tasks/bounceVhost.js +1 -1
- package/lib/amqp/tasks/checkExchanges.js +9 -5
- package/lib/amqp/tasks/checkQueues.js +9 -5
- package/lib/amqp/tasks/checkVhost.js +17 -13
- package/lib/amqp/tasks/closeChannel.js +0 -1
- package/lib/amqp/tasks/createChannel.js +0 -1
- package/lib/amqp/tasks/createConnection.js +18 -15
- package/lib/amqp/tasks/deleteExchanges.js +9 -5
- package/lib/amqp/tasks/deleteQueues.js +9 -5
- package/lib/amqp/tasks/deleteVhost.js +17 -13
- package/lib/amqp/tasks/forewarnVhost.js +1 -1
- package/lib/amqp/tasks/initCounters.js +12 -8
- package/lib/amqp/tasks/initPublications.js +13 -9
- package/lib/amqp/tasks/initShovels.js +9 -5
- package/lib/amqp/tasks/initSubscriptions.js +12 -8
- package/lib/amqp/tasks/initVhosts.js +16 -12
- package/lib/amqp/tasks/nukeVhost.js +1 -1
- package/lib/amqp/tasks/purgeQueues.js +9 -5
- package/lib/amqp/tasks/purgeVhost.js +1 -1
- package/lib/amqp/tasks/shutdownVhost.js +1 -1
- package/lib/backoff/exponential.js +1 -2
- package/lib/backoff/index.js +1 -1
- package/lib/backoff/linear.js +2 -4
- package/lib/config/baseline.js +12 -23
- package/lib/config/configure.js +89 -41
- package/lib/config/tests.js +30 -27
- package/lib/config/validate.js +22 -3
- package/lib/counters/inMemoryCluster.js +33 -22
- package/lib/counters/index.js +1 -1
- package/lib/counters/stub.js +2 -3
- package/lib/management/client.js +3 -9
- package/lib/utils/setTimeoutUnref.js +1 -1
- package/package.json +12 -4
package/lib/amqp/Subscription.js
CHANGED
|
@@ -25,12 +25,12 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
25
25
|
|
|
26
26
|
this.name = config.name;
|
|
27
27
|
|
|
28
|
-
this.init = function(next) {
|
|
28
|
+
this.init = function (next) {
|
|
29
29
|
debug('Initialising subscription: %s', config.name);
|
|
30
30
|
return next(null, self);
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
this.subscribe = function(overrides, next) {
|
|
33
|
+
this.subscribe = function (overrides, next) {
|
|
34
34
|
const session = new SubscriberSession(sequentialChannelOperations, config);
|
|
35
35
|
subscribeLater(session, _.defaultsDeep(overrides, config));
|
|
36
36
|
return next(null, session);
|
|
@@ -82,6 +82,7 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
82
82
|
if (!message) return handleConsumerCancel(session, config, removeErrorHandlers);
|
|
83
83
|
|
|
84
84
|
debug('Received message: %s from queue: %s', message.properties.messageId, config.queue);
|
|
85
|
+
session._incrementUnacknowledgeMessageCount(message.fields.consumerTag);
|
|
85
86
|
|
|
86
87
|
decorateWithRoutingHeaders(message);
|
|
87
88
|
if (immediateNack(message)) return ackOrNack(session, message, true);
|
|
@@ -91,8 +92,7 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
91
92
|
if (redeliveriesExceeded(message)) return handleRedeliveriesExceeded(session, message);
|
|
92
93
|
|
|
93
94
|
getContent(message, config, (err, content) => {
|
|
94
|
-
err ? handleContentError(session, message, err)
|
|
95
|
-
: session.emit('message', message, content, getAckOrNack(session, message));
|
|
95
|
+
err ? handleContentError(session, message, err) : session.emit('message', message, content, getAckOrNack(session, message));
|
|
96
96
|
});
|
|
97
97
|
});
|
|
98
98
|
}
|
|
@@ -145,7 +145,7 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
function handleRedeliveriesError(err, session, message) {
|
|
148
|
-
debug('Error handling redeliveries of message %s: %s',
|
|
148
|
+
debug('Error handling redeliveries of message %s: %s', message.properties.messageId, err.message);
|
|
149
149
|
if (session.emit('redeliveries_error', err, message, getAckOrNack(session, message))) return;
|
|
150
150
|
if (session.emit('redeliveries_exceeded', err, message, getAckOrNack(session, message))) return;
|
|
151
151
|
nackAndError(session, message, err);
|
|
@@ -198,8 +198,7 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
function immediateNack(message) {
|
|
201
|
-
if (_.get(message,
|
|
202
|
-
if (_.get(message, format('properties.headers.rascal.recovery.%s.immediateNack', message.properties.headers.rascal.originalQueue))) return true;
|
|
201
|
+
if (_.get(message, ['properties', 'headers', 'rascal', 'recovery', message.properties.headers.rascal.originalQueue, 'immediateNack'])) return true;
|
|
203
202
|
return false;
|
|
204
203
|
}
|
|
205
204
|
|
|
@@ -215,8 +214,7 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
215
214
|
if (arguments.length === 3) return ackOrNack(session, message, err, undefined, emitOnError.bind(null, session));
|
|
216
215
|
if (arguments.length === 4 && _.isFunction(arguments[3])) return ackOrNack(session, message, err, undefined, arguments[3]);
|
|
217
216
|
if (arguments.length === 4) return ackOrNack(session, message, err, recovery, emitOnError.bind(null, session));
|
|
218
|
-
err ? subscriberError.handle(session, message, err, recovery, next)
|
|
219
|
-
: session._ack(message, next);
|
|
217
|
+
err ? subscriberError.handle(session, message, err, recovery, next) : session._ack(message, next);
|
|
220
218
|
}
|
|
221
219
|
|
|
222
220
|
function ackOrNackP(session, message, err, recovery) {
|
|
@@ -224,9 +222,10 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
224
222
|
if (arguments.length === 3) return ackOrNackP(session, message, err, undefined);
|
|
225
223
|
|
|
226
224
|
return new Promise((resolve, reject) => {
|
|
227
|
-
const cb = function(err) {
|
|
228
|
-
|
|
229
|
-
|
|
225
|
+
const cb = function (err) {
|
|
226
|
+
err ? reject(err) : resolve();
|
|
227
|
+
};
|
|
228
|
+
err ? subscriberError.handle(session, message, err, recovery, cb) : session._ack(message, cb);
|
|
230
229
|
});
|
|
231
230
|
}
|
|
232
231
|
|
|
@@ -256,12 +255,13 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
256
255
|
debug('Handling channel error: %s from %s using channel: %s', err.message, config.name, session._getRascalChannelId());
|
|
257
256
|
if (removeErrorHandlers) removeErrorHandlers();
|
|
258
257
|
session.emit('error', err);
|
|
259
|
-
config.retry &&
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
258
|
+
config.retry &&
|
|
259
|
+
subscribeNow(session, config, (err) => {
|
|
260
|
+
if (!err) return;
|
|
261
|
+
const delay = timer.next();
|
|
262
|
+
debug('Will attempt resubscription(%d) to %s in %dms', attempts + 1, config.name, delay);
|
|
263
|
+
session._schedule(handleChannelError.bind(null, session, config, null, attempts + 1, err), delay);
|
|
264
|
+
});
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
function handleConsumerCancel(session, config, removeErrorHandlers) {
|
|
@@ -271,12 +271,13 @@ function Subscription(broker, vhost, config, counter) {
|
|
|
271
271
|
if (err) debug('Error cancelling subscription: %s', err.message);
|
|
272
272
|
const cancelErr = new Error(format('Subscription: %s was cancelled by the broker', config.name));
|
|
273
273
|
session.emit('cancelled', cancelErr) || session.emit('error', cancelErr);
|
|
274
|
-
config.retry &&
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
274
|
+
config.retry &&
|
|
275
|
+
subscribeNow(session, config, (err) => {
|
|
276
|
+
if (!err) return;
|
|
277
|
+
const delay = timer.next();
|
|
278
|
+
debug('Will attempt resubscription(%d) to %s in %dms', 1, config.name, delay);
|
|
279
|
+
session._schedule(handleChannelError.bind(null, session, config, null, 1, err), delay);
|
|
280
|
+
});
|
|
280
281
|
});
|
|
281
282
|
}
|
|
282
283
|
}
|
package/lib/amqp/Vhost.js
CHANGED
|
@@ -19,7 +19,6 @@ module.exports = {
|
|
|
19
19
|
inherits(Vhost, EventEmitter);
|
|
20
20
|
|
|
21
21
|
function Vhost(config) {
|
|
22
|
-
|
|
23
22
|
const self = this;
|
|
24
23
|
let connection;
|
|
25
24
|
let connectionConfig;
|
|
@@ -41,7 +40,7 @@ function Vhost(config) {
|
|
|
41
40
|
|
|
42
41
|
pauseChannelAllocation();
|
|
43
42
|
|
|
44
|
-
this.init = function(next) {
|
|
43
|
+
this.init = function (next) {
|
|
45
44
|
if (shuttingDown) {
|
|
46
45
|
debug('Aborting initialisation. Vhost %s is shutting down.', self.name);
|
|
47
46
|
return next();
|
|
@@ -73,7 +72,7 @@ function Vhost(config) {
|
|
|
73
72
|
return self;
|
|
74
73
|
};
|
|
75
74
|
|
|
76
|
-
this.forewarn = function(next) {
|
|
75
|
+
this.forewarn = function (next) {
|
|
77
76
|
debug('Forewarning vhost: %s about impending shutdown', self.name);
|
|
78
77
|
pauseChannelAllocation();
|
|
79
78
|
shuttingDown = true;
|
|
@@ -81,7 +80,7 @@ function Vhost(config) {
|
|
|
81
80
|
next();
|
|
82
81
|
};
|
|
83
82
|
|
|
84
|
-
this.shutdown = function(next) {
|
|
83
|
+
this.shutdown = function (next) {
|
|
85
84
|
debug('Shutting down vhost: %s', self.name);
|
|
86
85
|
clearTimeout(reconnectTimeout);
|
|
87
86
|
pauseChannelAllocation();
|
|
@@ -91,7 +90,7 @@ function Vhost(config) {
|
|
|
91
90
|
});
|
|
92
91
|
};
|
|
93
92
|
|
|
94
|
-
this.nuke = function(next) {
|
|
93
|
+
this.nuke = function (next) {
|
|
95
94
|
debug('Nuking vhost: %s', self.name);
|
|
96
95
|
pauseChannelAllocation();
|
|
97
96
|
drainChannelPools((err) => {
|
|
@@ -104,7 +103,7 @@ function Vhost(config) {
|
|
|
104
103
|
});
|
|
105
104
|
};
|
|
106
105
|
|
|
107
|
-
this.purge = function(next) {
|
|
106
|
+
this.purge = function (next) {
|
|
108
107
|
debug('Purging vhost: %s', self.name);
|
|
109
108
|
purge(config, { purge: true, connectionIndex: self.connectionIndex }, (err) => {
|
|
110
109
|
if (err) return next(err);
|
|
@@ -113,21 +112,22 @@ function Vhost(config) {
|
|
|
113
112
|
});
|
|
114
113
|
};
|
|
115
114
|
|
|
116
|
-
this.bounce = function(next) {
|
|
117
|
-
async.series([
|
|
118
|
-
|
|
119
|
-
self.
|
|
120
|
-
|
|
115
|
+
this.bounce = function (next) {
|
|
116
|
+
async.series([self.disconnect, self.init], (err) => {
|
|
117
|
+
if (err) return next(err);
|
|
118
|
+
debug('Finished bouncing vhost: %s', self.name);
|
|
119
|
+
setImmediate(next);
|
|
120
|
+
});
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
this.connect = function(next) {
|
|
123
|
+
this.connect = function (next) {
|
|
124
124
|
debug('Connecting to vhost: %s', self.name);
|
|
125
125
|
connect(config, { connectionIndex: self.connectionIndex }, (err, config, ctx) => {
|
|
126
126
|
return next(err, ctx.connection);
|
|
127
127
|
});
|
|
128
128
|
};
|
|
129
129
|
|
|
130
|
-
this.disconnect = function(next) {
|
|
130
|
+
this.disconnect = function (next) {
|
|
131
131
|
debug('Disconnecting from vhost: %s', self.name);
|
|
132
132
|
if (!connection) return next();
|
|
133
133
|
connection.removeAllListeners();
|
|
@@ -140,51 +140,51 @@ function Vhost(config) {
|
|
|
140
140
|
});
|
|
141
141
|
};
|
|
142
142
|
|
|
143
|
-
this.getChannel = function(next) {
|
|
143
|
+
this.getChannel = function (next) {
|
|
144
144
|
channelCreator.push({ confirm: false }, next);
|
|
145
145
|
debug('Requested channel. Outstanding channel requests: %d', channelCreator.length());
|
|
146
146
|
};
|
|
147
147
|
|
|
148
|
-
this.getConfirmChannel = function(next) {
|
|
148
|
+
this.getConfirmChannel = function (next) {
|
|
149
149
|
channelCreator.push({ confirm: true }, next);
|
|
150
150
|
debug('Requested confirm channel. Outstanding channel requests: %d', channelCreator.length());
|
|
151
151
|
};
|
|
152
152
|
|
|
153
|
-
this.borrowChannel = function(next) {
|
|
153
|
+
this.borrowChannel = function (next) {
|
|
154
154
|
if (!regularChannelPool) return next(new Error(format('Vhost: %s must be initialised before you can borrow a channel', self.name)));
|
|
155
155
|
regularChannelPool.borrow(next);
|
|
156
156
|
};
|
|
157
157
|
|
|
158
|
-
this.returnChannel = function(channel) {
|
|
158
|
+
this.returnChannel = function (channel) {
|
|
159
159
|
if (!regularChannelPool) return;
|
|
160
160
|
regularChannelPool.release(channel);
|
|
161
161
|
};
|
|
162
162
|
|
|
163
|
-
this.destroyChannel = function(channel) {
|
|
163
|
+
this.destroyChannel = function (channel) {
|
|
164
164
|
if (!regularChannelPool) return;
|
|
165
165
|
regularChannelPool.destroy(channel);
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
-
this.borrowConfirmChannel = function(next) {
|
|
168
|
+
this.borrowConfirmChannel = function (next) {
|
|
169
169
|
if (!confirmChannelPool) return next(new Error(format('Vhost: %s must be initialised before you can borrow a confirm channel', self.name)));
|
|
170
170
|
confirmChannelPool.borrow(next);
|
|
171
171
|
};
|
|
172
172
|
|
|
173
|
-
this.returnConfirmChannel = function(channel) {
|
|
173
|
+
this.returnConfirmChannel = function (channel) {
|
|
174
174
|
if (!confirmChannelPool) return;
|
|
175
175
|
confirmChannelPool.release(channel);
|
|
176
176
|
};
|
|
177
177
|
|
|
178
|
-
this.destroyConfirmChannel = function(channel) {
|
|
178
|
+
this.destroyConfirmChannel = function (channel) {
|
|
179
179
|
if (!confirmChannelPool) return;
|
|
180
180
|
confirmChannelPool.destroy(channel);
|
|
181
181
|
};
|
|
182
182
|
|
|
183
|
-
this.isPaused = function() {
|
|
183
|
+
this.isPaused = function () {
|
|
184
184
|
return paused;
|
|
185
185
|
};
|
|
186
186
|
|
|
187
|
-
this.getConnectionDetails = function() {
|
|
187
|
+
this.getConnectionDetails = function () {
|
|
188
188
|
return { vhost: self.name, connectionUrl: connectionConfig.loggableUrl };
|
|
189
189
|
};
|
|
190
190
|
|
|
@@ -281,37 +281,46 @@ function Vhost(config) {
|
|
|
281
281
|
|
|
282
282
|
function release(channel) {
|
|
283
283
|
debug('Releasing %s channel: %s. %o', mode, channel._rascal_id, stats());
|
|
284
|
-
pool
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
284
|
+
pool
|
|
285
|
+
.release(channel)
|
|
286
|
+
.catch((err) => {
|
|
287
|
+
debug('Error releasing %s channel: %s. %s', mode, channel._rascal_id, err.message);
|
|
288
|
+
})
|
|
289
|
+
.then(() => {
|
|
290
|
+
if (poolQueue.length() > 0 || !busy) return;
|
|
291
|
+
busy = false;
|
|
292
|
+
self.emit('ready', stats());
|
|
293
|
+
});
|
|
291
294
|
}
|
|
292
295
|
|
|
293
296
|
function destroy(channel) {
|
|
294
297
|
debug('Destroying %s channel: %s. %o', mode, channel._rascal_id, stats());
|
|
295
|
-
pool
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
298
|
+
pool
|
|
299
|
+
.destroy(channel)
|
|
300
|
+
.catch((err) => {
|
|
301
|
+
debug('Error destroying %s channel: %s. %s', mode, channel._rascal_id, err.message);
|
|
302
|
+
})
|
|
303
|
+
.then(() => {
|
|
304
|
+
if (poolQueue.length() > 0 || !busy) return;
|
|
305
|
+
busy = false;
|
|
306
|
+
self.emit('ready', stats());
|
|
307
|
+
});
|
|
302
308
|
}
|
|
303
309
|
|
|
304
310
|
function drain(next) {
|
|
305
311
|
debug('Draining %s channel pool. %o', mode, stats());
|
|
306
|
-
pool
|
|
307
|
-
|
|
308
|
-
|
|
312
|
+
pool
|
|
313
|
+
.drain()
|
|
314
|
+
.then(() => {
|
|
315
|
+
return pool.clear().then(() => {
|
|
316
|
+
debug('Drained %s channel pool. %o', mode, stats());
|
|
317
|
+
setImmediate(next);
|
|
318
|
+
});
|
|
319
|
+
})
|
|
320
|
+
.catch((err) => {
|
|
321
|
+
debug('Error draining %s channel pool. %s', mode, err.message);
|
|
309
322
|
setImmediate(next);
|
|
310
323
|
});
|
|
311
|
-
}).catch((err) => {
|
|
312
|
-
debug('Error draining %s channel pool. %s', mode, err.message);
|
|
313
|
-
setImmediate(next);
|
|
314
|
-
});
|
|
315
324
|
}
|
|
316
325
|
|
|
317
326
|
debug('Creating %s channel pool %o', mode, options.pool);
|
|
@@ -324,11 +333,14 @@ function Vhost(config) {
|
|
|
324
333
|
});
|
|
325
334
|
|
|
326
335
|
poolQueue = async.queue((__, next) => {
|
|
327
|
-
pool
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
336
|
+
pool
|
|
337
|
+
.acquire()
|
|
338
|
+
.then((channel) => {
|
|
339
|
+
setImmediate(() => {
|
|
340
|
+
next(null, channel);
|
|
341
|
+
});
|
|
342
|
+
})
|
|
343
|
+
.catch(next);
|
|
332
344
|
}, 1);
|
|
333
345
|
|
|
334
346
|
return {
|
|
@@ -351,13 +363,12 @@ function Vhost(config) {
|
|
|
351
363
|
});
|
|
352
364
|
function onVhostInitialised() {
|
|
353
365
|
debug('Vhost: %s was initialised. Resuming channel creation', self.name);
|
|
354
|
-
createChannel(confirm, next);
|
|
366
|
+
createChannel(confirm, next);
|
|
355
367
|
}
|
|
356
368
|
self.once('vhost_initialised', onVhostInitialised);
|
|
357
369
|
}
|
|
358
370
|
|
|
359
371
|
function createChannel(confirm, next) {
|
|
360
|
-
|
|
361
372
|
if (shuttingDown) {
|
|
362
373
|
debug('Ignoring create channel request. Vhost: %s is shutting down.', self.name);
|
|
363
374
|
return next();
|
|
@@ -392,6 +403,7 @@ function Vhost(config) {
|
|
|
392
403
|
|
|
393
404
|
channel._rascal_id = channelId;
|
|
394
405
|
channel.connection._rascal_id = connection._rascal_id;
|
|
406
|
+
channel.connection.setMaxListeners(0);
|
|
395
407
|
debug('Created %s channel: %s from connection: %s', getChannelMode(confirm), channel._rascal_id, connection._rascal_id);
|
|
396
408
|
|
|
397
409
|
// See https://github.com/squaremo/amqp.node/issues/388
|
|
@@ -434,19 +446,32 @@ function Vhost(config) {
|
|
|
434
446
|
}
|
|
435
447
|
|
|
436
448
|
function ensureChannelPools() {
|
|
437
|
-
regularChannelPool =
|
|
438
|
-
|
|
449
|
+
regularChannelPool =
|
|
450
|
+
regularChannelPool ||
|
|
451
|
+
createChannelPool({
|
|
452
|
+
confirm: false,
|
|
453
|
+
pool: config.publicationChannelPools.regularPool,
|
|
454
|
+
});
|
|
455
|
+
confirmChannelPool =
|
|
456
|
+
confirmChannelPool ||
|
|
457
|
+
createChannelPool({
|
|
458
|
+
confirm: true,
|
|
459
|
+
pool: config.publicationChannelPools.confirmPool,
|
|
460
|
+
});
|
|
439
461
|
}
|
|
440
462
|
|
|
441
463
|
function drainChannelPools(next) {
|
|
442
|
-
async.series(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
464
|
+
async.series(
|
|
465
|
+
[
|
|
466
|
+
function (cb) {
|
|
467
|
+
regularChannelPool ? regularChannelPool.drain(cb) : cb();
|
|
468
|
+
},
|
|
469
|
+
function (cb) {
|
|
470
|
+
confirmChannelPool ? confirmChannelPool.drain(cb) : cb();
|
|
471
|
+
},
|
|
472
|
+
],
|
|
473
|
+
next
|
|
474
|
+
);
|
|
450
475
|
}
|
|
451
476
|
|
|
452
477
|
function attachErrorHandlers(config) {
|
|
@@ -462,11 +487,12 @@ function Vhost(config) {
|
|
|
462
487
|
connection = undefined;
|
|
463
488
|
self.emit('disconnect');
|
|
464
489
|
self.emit('error', err, self.getConnectionDetails());
|
|
465
|
-
connectionConfig.retry &&
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
490
|
+
connectionConfig.retry &&
|
|
491
|
+
self.init((err) => {
|
|
492
|
+
if (!err) return;
|
|
493
|
+
const delay = timer.next();
|
|
494
|
+
debug('Will attempt reconnection in in %dms', delay);
|
|
495
|
+
reconnectTimeout = setTimeoutUnref(handleConnectionError.bind(null, borked, config, err), delay);
|
|
496
|
+
});
|
|
471
497
|
}
|
|
472
498
|
}
|
|
@@ -4,17 +4,20 @@ const _ = require('lodash');
|
|
|
4
4
|
const async = require('async');
|
|
5
5
|
|
|
6
6
|
module.exports = _.curry((config, ctx, next) => {
|
|
7
|
-
|
|
8
7
|
const bind = {
|
|
9
8
|
queue: bindQueue,
|
|
10
9
|
exchange: bindExchange,
|
|
11
10
|
};
|
|
12
11
|
|
|
13
|
-
async.eachSeries(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
async.eachSeries(
|
|
13
|
+
_.values(config.bindings),
|
|
14
|
+
(binding, callback) => {
|
|
15
|
+
bind[binding.destinationType](config, ctx.channel, binding, callback);
|
|
16
|
+
},
|
|
17
|
+
(err) => {
|
|
18
|
+
next(err, config, ctx);
|
|
19
|
+
}
|
|
20
|
+
);
|
|
18
21
|
});
|
|
19
22
|
|
|
20
23
|
function bindQueue(config, channel, binding, next) {
|
|
@@ -3,11 +3,15 @@ const _ = require('lodash');
|
|
|
3
3
|
const async = require('async');
|
|
4
4
|
|
|
5
5
|
module.exports = _.curry((config, ctx, next) => {
|
|
6
|
-
async.eachSeries(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
async.eachSeries(
|
|
7
|
+
_.keys(config.exchanges),
|
|
8
|
+
(name, callback) => {
|
|
9
|
+
assertExchange(ctx.channel, config.exchanges[name], callback);
|
|
10
|
+
},
|
|
11
|
+
(err) => {
|
|
12
|
+
next(err, config, ctx);
|
|
13
|
+
}
|
|
14
|
+
);
|
|
11
15
|
});
|
|
12
16
|
|
|
13
17
|
function assertExchange(channel, config, next) {
|
|
@@ -3,11 +3,15 @@ const _ = require('lodash');
|
|
|
3
3
|
const async = require('async');
|
|
4
4
|
|
|
5
5
|
module.exports = _.curry((config, ctx, next) => {
|
|
6
|
-
async.eachSeries(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
async.eachSeries(
|
|
7
|
+
_.keys(config.queues),
|
|
8
|
+
(name, callback) => {
|
|
9
|
+
assertQueue(ctx.channel, config.queues[name], callback);
|
|
10
|
+
},
|
|
11
|
+
(err) => {
|
|
12
|
+
next(err, config, ctx);
|
|
13
|
+
}
|
|
14
|
+
);
|
|
11
15
|
});
|
|
12
16
|
|
|
13
17
|
function assertQueue(channel, config, next) {
|
|
@@ -7,17 +7,21 @@ module.exports = _.curry((config, ctx, next) => {
|
|
|
7
7
|
if (!config.assert) return next(null, config, ctx);
|
|
8
8
|
const candidates = config.connections;
|
|
9
9
|
|
|
10
|
-
async.retry(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
async.retry(
|
|
11
|
+
candidates.length,
|
|
12
|
+
(cb) => {
|
|
13
|
+
const connectionConfig = candidates[ctx.connectionIndex];
|
|
14
|
+
client.assertVhost(config.name, connectionConfig.management, (err) => {
|
|
15
|
+
if (err) {
|
|
16
|
+
ctx.connectionIndex = (ctx.connectionIndex + 1) % candidates.length;
|
|
17
|
+
return cb(err);
|
|
18
|
+
}
|
|
19
|
+
ctx.connectionConfig = connectionConfig;
|
|
20
|
+
cb();
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
(err) => {
|
|
24
|
+
next(err, config, ctx);
|
|
25
|
+
}
|
|
26
|
+
);
|
|
23
27
|
});
|
|
@@ -3,11 +3,15 @@ const _ = require('lodash');
|
|
|
3
3
|
const async = require('async');
|
|
4
4
|
|
|
5
5
|
module.exports = _.curry((config, ctx, next) => {
|
|
6
|
-
async.eachSeries(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
async.eachSeries(
|
|
7
|
+
_.keys(config.exchanges),
|
|
8
|
+
(name, callback) => {
|
|
9
|
+
checkExchange(ctx.channel, config.exchanges[name], callback);
|
|
10
|
+
},
|
|
11
|
+
(err) => {
|
|
12
|
+
next(err, config, ctx);
|
|
13
|
+
}
|
|
14
|
+
);
|
|
11
15
|
});
|
|
12
16
|
|
|
13
17
|
function checkExchange(channel, config, next) {
|
|
@@ -3,11 +3,15 @@ const _ = require('lodash');
|
|
|
3
3
|
const async = require('async');
|
|
4
4
|
|
|
5
5
|
module.exports = _.curry((config, ctx, next) => {
|
|
6
|
-
async.eachSeries(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
async.eachSeries(
|
|
7
|
+
_.keys(config.queues),
|
|
8
|
+
(name, callback) => {
|
|
9
|
+
checkQueue(ctx.channel, config.queues[name], callback);
|
|
10
|
+
},
|
|
11
|
+
(err) => {
|
|
12
|
+
next(err, config, ctx);
|
|
13
|
+
}
|
|
14
|
+
);
|
|
11
15
|
});
|
|
12
16
|
|
|
13
17
|
function checkQueue(channel, config, next) {
|
|
@@ -7,17 +7,21 @@ module.exports = _.curry((config, ctx, next) => {
|
|
|
7
7
|
if (!config.check) return next(null, config, ctx);
|
|
8
8
|
const candidates = config.connections;
|
|
9
9
|
|
|
10
|
-
async.retry(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
async.retry(
|
|
11
|
+
candidates.length,
|
|
12
|
+
(cb) => {
|
|
13
|
+
const connectionConfig = candidates[ctx.connectionIndex];
|
|
14
|
+
client.checkVhost(config.name, connectionConfig.management, (err) => {
|
|
15
|
+
if (err) {
|
|
16
|
+
ctx.connectionIndex = (ctx.connectionIndex + 1) % candidates.length;
|
|
17
|
+
return cb(err);
|
|
18
|
+
}
|
|
19
|
+
ctx.connectionConfig = connectionConfig;
|
|
20
|
+
cb();
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
(err) => {
|
|
24
|
+
next(err, config, ctx);
|
|
25
|
+
}
|
|
26
|
+
);
|
|
23
27
|
});
|