rascal 14.0.0 → 14.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ ## 14.2.1
4
+
5
+ - Fix schema bug
6
+
7
+ ## 14.2.0
8
+
9
+ - Add json schema (lib/config/schema.json) - See https://github.com/guidesmiths/rascal/issues/168
10
+
11
+ ## 14.1.0
12
+
13
+ - Adds support for custom user agents - See https://github.com/guidesmiths/rascal/issues/170
14
+
15
+ ## 14.0.1
16
+
17
+ - Fixes https://github.com/guidesmiths/rascal/issues/178
18
+
3
19
  ## 14.0.0
4
20
 
5
21
  - Rather than waiting an arbitrary time for channels to close when cancelling a subscription, Rascal now waits until any outstanding messages have been acknowledged. By default, Rascal will wait indefinitely, but this behaviour can be overriden by specifying a subscription.closeTimeout. If the timeout is exceeded following a direct call to `broker.unsubscribeAll` or `subscription.cancel` then an error will be yielded. If the timeout is exceeded following an indirect call to `subscription.cancel` (e.g. by `broker.shutdown`) then an error will be emitted but the operation will be allowed to continue.
package/README.md CHANGED
@@ -273,10 +273,11 @@ The most common configuration options are
273
273
  - [publications](#publications)
274
274
  - [subscriptions](#subscriptions)
275
275
 
276
- A simple configuration is shown below.
276
+ A simple configuration is shown below. You can reference Rascal's JSON schema from the config to enable validation and suggestions in compatible IDEs.
277
277
 
278
278
  ```json
279
279
  {
280
+ "$schema": "./node_modules/rascal/lib/config/schema.json",
280
281
  "vhosts": {
281
282
  "/": {
282
283
  "connection": {
@@ -483,6 +484,15 @@ Rascal uses [superagent](https://github.com/visionmedia/superagent) under the ho
483
484
  }
484
485
  ```
485
486
 
487
+ You can also supply your own agent via the broker components. Use this when you need to set [TLS options](https://visionmedia.github.io/superagent/#tls-options).
488
+
489
+ ```js
490
+ const superagent = require('superagent-defaults');
491
+ const agent = superagent().on('request', (req) => console.log(req.url));
492
+ const components = { agent };
493
+ const broker = await Broker.create(config, components);
494
+ ```
495
+
486
496
  #### assert
487
497
 
488
498
  When set to true, Rascal will create the vhost if one doesn't exist using the RabbitMQ management API. This requires the [management plugin](https://www.rabbitmq.com/management.html) to be installed on the broker and for the management user to have necessary permissions.
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "publicationChannelPools": {
6
+ "confirmPool": {
7
+ "max": 10,
8
+ "min": 10,
9
+ "evictionRunIntervalMillis": 1000,
10
+ "idleTimeoutMillis": 5000,
11
+ "autostart": true
12
+ }
13
+ },
14
+ "connection": {
15
+ "heartbeat": 5,
16
+ "socketOptions": {
17
+ "timeout": 1000
18
+ }
19
+ },
20
+ "exchanges": ["demo_ex"],
21
+ "queues": ["demo_q"],
22
+ "bindings": ["demo_ex[a.b.c] -> demo_q"],
23
+ "publications": {
24
+ "demo_pub": {
25
+ "exchange": "demo_ex",
26
+ "routingKey": "a.b.c",
27
+ "confirm": false,
28
+ "options": {
29
+ "persistent": false
30
+ }
31
+ }
32
+ },
33
+ "subscriptions": {
34
+ "demo_sub": {
35
+ "queue": "demo_q"
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "connection": {
6
+ "heartbeat": 1,
7
+ "socketOptions": {
8
+ "timeout": 1000
9
+ }
10
+ },
11
+ "exchanges": [""],
12
+ "queues": ["demo_q"],
13
+ "publications": {
14
+ "demo_pub": {
15
+ "exchange": ""
16
+ }
17
+ },
18
+ "subscriptions": {
19
+ "demo_sub": {
20
+ "queue": "demo_q"
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "exchanges": ["demo_ex"],
6
+ "queues": ["demo_q"],
7
+ "bindings": ["demo_ex[a.b.c] -> demo_q"],
8
+ "publications": {
9
+ "demo_pub": {
10
+ "exchange": "demo_ex",
11
+ "routingKey": "a.b.c"
12
+ }
13
+ },
14
+ "subscriptions": {
15
+ "demo_sub": {
16
+ "queue": "demo_q"
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "connection": {
6
+ "heartbeat": 1,
7
+ "socketOptions": {
8
+ "timeout": 1000
9
+ }
10
+ },
11
+ "exchanges": ["demo_ex"],
12
+ "queues": ["demo_q"],
13
+ "bindings": ["demo_ex[a.b.c] -> demo_q"],
14
+ "publications": {
15
+ "demo_pub": {
16
+ "exchange": "demo_ex",
17
+ "routingKey": "a.b.c"
18
+ }
19
+ },
20
+ "subscriptions": {
21
+ "demo_sub": {
22
+ "queue": "demo_q"
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "../../lib/config/schema.json",
3
+ "vhosts": {
4
+ "/": {
5
+ "publicationChannelPools": {
6
+ "confirmPool": {
7
+ "autostart": true
8
+ }
9
+ },
10
+ "connection": {
11
+ "options": {
12
+ "heartbeat": 10
13
+ },
14
+ "socketOptions": {
15
+ "timeout": 1000
16
+ }
17
+ },
18
+ "exchanges": ["demo_ex"],
19
+ "queues": ["demo_q"],
20
+ "bindings": ["demo_ex[a.b.c] -> demo_q"],
21
+ "publications": {
22
+ "demo_pub": {
23
+ "exchange": "demo_ex",
24
+ "routingKey": "a.b.c",
25
+ "options": {
26
+ "persistent": false
27
+ }
28
+ }
29
+ },
30
+ "subscriptions": {
31
+ "demo_sub": {
32
+ "queue": "demo_q"
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
@@ -18,9 +18,16 @@ const maxInterval = 2147483647;
18
18
  module.exports = {
19
19
  create: function create(config, components, next) {
20
20
  if (arguments.length === 2) return create(config, {}, arguments[1]);
21
+
22
+ const counters = _.defaults({}, components.counters, {
23
+ stub,
24
+ inMemory,
25
+ inMemoryCluster,
26
+ });
27
+
21
28
  preflight(_.cloneDeep(config), (err, config) => {
22
29
  if (err) return next(err);
23
- new Broker(config, components)._init(next);
30
+ new Broker(config, _.assign({}, components, { counters }))._init(next);
24
31
  });
25
32
  },
26
33
  };
@@ -39,11 +46,6 @@ function Broker(config, components) {
39
46
  const forewarnVhost = tasks.forewarnVhost;
40
47
  const shutdownVhost = tasks.shutdownVhost;
41
48
  const bounceVhost = tasks.bounceVhost;
42
- const counters = _.defaults({}, components.counters, {
43
- stub,
44
- inMemory,
45
- inMemoryCluster,
46
- });
47
49
 
48
50
  this.config = config;
49
51
  this.promises = false;
@@ -54,7 +56,7 @@ function Broker(config, components) {
54
56
  publications = {};
55
57
  subscriptions = {};
56
58
  sessions = [];
57
- init(config, { broker: self, components: { counters } }, (err) => {
59
+ init(config, { broker: self, components }, (err) => {
58
60
  self.keepActive = setInterval(_.noop, maxInterval);
59
61
  setImmediate(() => {
60
62
  next(err, self);
@@ -135,7 +137,7 @@ function Broker(config, components) {
135
137
  async.eachSeries(
136
138
  _.values(vhosts),
137
139
  (vhost, callback) => {
138
- nukeVhost(config, { vhost }, callback);
140
+ nukeVhost(config, { vhost, components }, callback);
139
141
  },
140
142
  (err) => {
141
143
  if (err) return next(err);
package/lib/amqp/Vhost.js CHANGED
@@ -11,14 +11,14 @@ const backoff = require('../backoff');
11
11
  const setTimeoutUnref = require('../utils/setTimeoutUnref');
12
12
 
13
13
  module.exports = {
14
- create(config, next) {
15
- new Vhost(config).init(next);
14
+ create(config, components, next) {
15
+ new Vhost(config, components).init(next);
16
16
  },
17
17
  };
18
18
 
19
19
  inherits(Vhost, EventEmitter);
20
20
 
21
- function Vhost(config) {
21
+ function Vhost(config, components) {
22
22
  const self = this;
23
23
  let connection;
24
24
  let connectionConfig;
@@ -49,7 +49,7 @@ function Vhost(config) {
49
49
  debug('Initialising vhost: %s', self.name);
50
50
  pauseChannelAllocation();
51
51
 
52
- init(config, { connectionIndex: self.connectionIndex }, (err, config, ctx) => {
52
+ init(config, { connectionIndex: self.connectionIndex, components }, (err, config, ctx) => {
53
53
  if (err) return next(err);
54
54
 
55
55
  connection = ctx.connection;
@@ -403,6 +403,7 @@ function Vhost(config) {
403
403
 
404
404
  channel._rascal_id = channelId;
405
405
  channel.connection._rascal_id = connection._rascal_id;
406
+ channel.connection.setMaxListeners(0);
406
407
  debug('Created %s channel: %s from connection: %s', getChannelMode(confirm), channel._rascal_id, connection._rascal_id);
407
408
 
408
409
  // See https://github.com/squaremo/amqp.node/issues/388
@@ -1,11 +1,13 @@
1
1
  const debug = require('debug')('rascal:tasks:assertVhost');
2
2
  const _ = require('lodash');
3
3
  const async = require('async');
4
- const client = require('../../management/client');
4
+ const Client = require('../../management/Client');
5
5
 
6
6
  module.exports = _.curry((config, ctx, next) => {
7
7
  if (!config.assert) return next(null, config, ctx);
8
+
8
9
  const candidates = config.connections;
10
+ const client = new Client(ctx.components.agent);
9
11
 
10
12
  async.retry(
11
13
  candidates.length,
@@ -1,11 +1,13 @@
1
1
  const debug = require('debug')('rascal:tasks:checkVhost');
2
2
  const _ = require('lodash');
3
3
  const async = require('async');
4
- const client = require('../../management/client');
4
+ const Client = require('../../management/Client');
5
5
 
6
6
  module.exports = _.curry((config, ctx, next) => {
7
7
  if (!config.check) return next(null, config, ctx);
8
+
8
9
  const candidates = config.connections;
10
+ const client = new Client(ctx.components.agent);
9
11
 
10
12
  async.retry(
11
13
  candidates.length,
@@ -1,13 +1,14 @@
1
1
  const debug = require('debug')('rascal:tasks:deleteVhost');
2
2
  const _ = require('lodash');
3
3
  const async = require('async');
4
- const client = require('../../management/client');
4
+ const Client = require('../../management/Client');
5
5
 
6
6
  module.exports = _.curry((config, ctx, next) => {
7
7
  const vhostConfig = config.vhosts[ctx.vhost.name];
8
8
  if (!vhostConfig.assert) return next(null, config, ctx);
9
9
 
10
10
  const candidates = vhostConfig.connections;
11
+ const client = new Client(ctx.components.agent);
11
12
 
12
13
  async.retry(
13
14
  candidates.length,
@@ -9,7 +9,7 @@ module.exports = _.curry((config, ctx, next) => {
9
9
  async.eachSeries(
10
10
  _.values(config.vhosts),
11
11
  (vhostConfig, callback) => {
12
- initVhost(vhostConfig, (err, vhost) => {
12
+ initVhost(vhostConfig, ctx.components, (err, vhost) => {
13
13
  if (err) return callback(err);
14
14
  vhost.setMaxListeners(0);
15
15
  forwardEvents(vhost, ctx.broker);
@@ -24,6 +24,6 @@ module.exports = _.curry((config, ctx, next) => {
24
24
  );
25
25
  });
26
26
 
27
- function initVhost(config, next) {
28
- Vhost.create(config, next);
27
+ function initVhost(config, components, next) {
28
+ Vhost.create(config, components, next);
29
29
  }
@@ -0,0 +1,682 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "vhosts": {
6
+ "type": "object",
7
+ "patternProperties": {
8
+ ".*": {
9
+ "$ref": "#/definitions/vhost"
10
+ }
11
+ }
12
+ },
13
+ "publications": {
14
+ "type": "object",
15
+ "patternProperties": {
16
+ ".*": {
17
+ "$ref": "#/definitions/publication"
18
+ }
19
+ }
20
+ },
21
+ "subscriptions": {
22
+ "type": "object",
23
+ "patternProperties": {
24
+ ".*": {
25
+ "$ref": "#/definitions/subscription"
26
+ }
27
+ }
28
+ },
29
+ "redeliveries": {
30
+ "$ref": "#/definitions/redeliveries"
31
+ },
32
+ "encryption": {
33
+ "type": "object",
34
+ "$ref": "#/definitions/encryption"
35
+ }
36
+ },
37
+ "definitions": {
38
+ "vhost": {
39
+ "type": "object",
40
+ "properties": {
41
+ "assert": {
42
+ "type": "boolean"
43
+ },
44
+ "check": {
45
+ "type": "boolean"
46
+ },
47
+ "connectionStrategy": {
48
+ "type": "string",
49
+ "enum": ["random", "fixed"]
50
+ },
51
+ "connection": {
52
+ "$ref": "#/definitions/connection"
53
+ },
54
+ "connections": {
55
+ "type": "array",
56
+ "items": {
57
+ "$ref": "#/definitions/connection"
58
+ }
59
+ },
60
+ "exchanges": {
61
+ "oneOf": [
62
+ {
63
+ "type": "array",
64
+ "items": {
65
+ "type": "string"
66
+ }
67
+ },
68
+ {
69
+ "type": "object",
70
+ "patternProperties": {
71
+ ".*": {
72
+ "$ref": "#/definitions/exchange"
73
+ }
74
+ }
75
+ }
76
+ ]
77
+ },
78
+ "queues": {
79
+ "oneOf": [
80
+ {
81
+ "type": "array",
82
+ "items": {
83
+ "type": "string"
84
+ }
85
+ },
86
+ {
87
+ "type": "object",
88
+ "patternProperties": {
89
+ ".*": {
90
+ "$ref": "#/definitions/queue"
91
+ }
92
+ }
93
+ }
94
+ ]
95
+ },
96
+ "bindings": {
97
+ "oneOf": [
98
+ {
99
+ "type": "array",
100
+ "items": {
101
+ "type": "string"
102
+ }
103
+ },
104
+ {
105
+ "type": "object",
106
+ "patternProperties": {
107
+ ".*": {
108
+ "$ref": "#/definitions/binding"
109
+ }
110
+ }
111
+ }
112
+ ]
113
+ },
114
+ "publications": {
115
+ "type": "object",
116
+ "patternProperties": {
117
+ ".*": {
118
+ "$ref": "#/definitions/publication"
119
+ }
120
+ }
121
+ },
122
+ "subscriptions": {
123
+ "type": "object",
124
+ "patternProperties": {
125
+ ".*": {
126
+ "$ref": "#/definitions/subscription"
127
+ }
128
+ }
129
+ },
130
+ "publicationChannelPools": {
131
+ "type": "object",
132
+ "properties": {
133
+ "regularPool": {
134
+ "$ref": "#/definitions/channelPool"
135
+ },
136
+ "confirmPool": {
137
+ "$ref": "#/definitions/channelPool"
138
+ }
139
+ }
140
+ }
141
+ }
142
+ },
143
+ "channelPool": {
144
+ "type": "object",
145
+ "properties": {
146
+ "autostart": {
147
+ "type": "boolean"
148
+ },
149
+ "max": {
150
+ "type": "integer",
151
+ "minimum": 0
152
+ },
153
+ "min": {
154
+ "type": "integer",
155
+ "minimum": 0
156
+ },
157
+ "evictionRunIntervalMillis": {
158
+ "type": "integer",
159
+ "minimum": 0
160
+ },
161
+ "idleTimeoutMillis": {
162
+ "type": "integer",
163
+ "minimum": 0
164
+ },
165
+ "rejectionDelayMillis": {
166
+ "type": "integer",
167
+ "minimum": 0
168
+ },
169
+ "testOnBorrow": {
170
+ "type": "boolean"
171
+ },
172
+ "acquireTimeoutMillis": {
173
+ "type": "integer",
174
+ "minimum": 0
175
+ },
176
+ "destroyTimeoutMillis": {
177
+ "type": "integer",
178
+ "minimum": 0
179
+ }
180
+ }
181
+ },
182
+ "connection": {
183
+ "anyOf": [
184
+ {
185
+ "type": "string"
186
+ },
187
+ {
188
+ "type": "object",
189
+ "properties": {
190
+ "url": {
191
+ "type": "string"
192
+ },
193
+ "options": {
194
+ "$ref": "#/definitions/connectOptions"
195
+ },
196
+ "socketOptions": {
197
+ "$ref": "#/definitions/socketOptions"
198
+ },
199
+ "retry": {
200
+ "$ref": "#/definitions/retry"
201
+ },
202
+ "management": {
203
+ "$ref": "#/definitions/management"
204
+ }
205
+ }
206
+ },
207
+ {
208
+ "type": "object",
209
+ "properties": {
210
+ "protocol": {
211
+ "type": "string",
212
+ "enum": ["amqp", "amqps"]
213
+ },
214
+ "hostname": {
215
+ "type": "string"
216
+ },
217
+ "user": {
218
+ "type": "string"
219
+ },
220
+ "password": {
221
+ "type": "string"
222
+ },
223
+ "port": {
224
+ "type": "integer",
225
+ "minimum": 1
226
+ },
227
+ "vhost": {
228
+ "type": "string"
229
+ },
230
+ "options": {
231
+ "$ref": "#/definitions/connectOptions"
232
+ },
233
+ "socketOptions": {
234
+ "type": "object"
235
+ },
236
+ "retry": {
237
+ "$ref": "#/definitions/retry"
238
+ },
239
+ "management": {
240
+ "$ref": "#/definitions/management"
241
+ }
242
+ }
243
+ }
244
+ ]
245
+ },
246
+ "connectOptions": {
247
+ "type": "object",
248
+ "properties": {
249
+ "frameMax": {
250
+ "type": "integer",
251
+ "minimum": 0
252
+ },
253
+ "heartbeat": {
254
+ "type": "integer",
255
+ "minimum": 0
256
+ },
257
+ "connection_timeout": {
258
+ "type": "integer",
259
+ "minimum": 0
260
+ },
261
+ "channelMax": {
262
+ "type": "integer",
263
+ "minimum": 0
264
+ }
265
+ }
266
+ },
267
+ "socketOptions": {
268
+ "type": "object",
269
+ "properties": {
270
+ "timeout": {
271
+ "type": "integer",
272
+ "minimum": 0
273
+ }
274
+ }
275
+ },
276
+ "management": {
277
+ "anyOf": [
278
+ {
279
+ "type": "object",
280
+ "properties": {
281
+ "url": {
282
+ "type": "string"
283
+ },
284
+ "options": {
285
+ "type": "object",
286
+ "properties": {
287
+ "timeout": {
288
+ "type": "integer",
289
+ "minimum": 0
290
+ }
291
+ }
292
+ }
293
+ }
294
+ },
295
+ {
296
+ "type": "object",
297
+ "properties": {
298
+ "protocol": {
299
+ "type": "string",
300
+ "enum": ["http", "https"]
301
+ },
302
+ "hostname": {
303
+ "type": "string"
304
+ },
305
+ "user": {
306
+ "type": "string"
307
+ },
308
+ "password": {
309
+ "type": "string"
310
+ },
311
+ "port": {
312
+ "type": "integer",
313
+ "minimum": 1
314
+ },
315
+ "options": {
316
+ "type": "object",
317
+ "properties": {
318
+ "timeout": {
319
+ "type": "integer",
320
+ "minimum": 0
321
+ }
322
+ }
323
+ }
324
+ }
325
+ }
326
+ ]
327
+ },
328
+ "exchange": {
329
+ "type": "object",
330
+ "properties": {
331
+ "name": {
332
+ "type": "string"
333
+ },
334
+ "assert": {
335
+ "type": "boolean"
336
+ },
337
+ "check": {
338
+ "type": "boolean"
339
+ },
340
+ "type": {
341
+ "type": "string"
342
+ },
343
+ "options": {
344
+ "type": "object",
345
+ "properties": {
346
+ "durable": {
347
+ "type": "boolean"
348
+ },
349
+ "internal": {
350
+ "type": "boolean"
351
+ },
352
+ "autoDelete": {
353
+ "type": "boolean"
354
+ },
355
+ "alternateExchange": {
356
+ "type": "string"
357
+ },
358
+ "expires": {
359
+ "type": "integer",
360
+ "minimum": 0
361
+ },
362
+ "arguments": {
363
+ "type": "object"
364
+ }
365
+ }
366
+ }
367
+ }
368
+ },
369
+ "queue": {
370
+ "type": "object",
371
+ "properties": {
372
+ "name": {
373
+ "type": "string"
374
+ },
375
+ "assert": {
376
+ "type": "boolean"
377
+ },
378
+ "check": {
379
+ "type": "boolean"
380
+ },
381
+ "type": {
382
+ "type": "string"
383
+ },
384
+ "purge": {
385
+ "type": "boolean"
386
+ },
387
+ "options": {
388
+ "type": "object",
389
+ "properties": {
390
+ "exclusive": {
391
+ "type": "boolean"
392
+ },
393
+ "durable": {
394
+ "type": "boolean"
395
+ },
396
+ "autoDelete": {
397
+ "type": "boolean"
398
+ },
399
+ "messageTtl": {
400
+ "type": "integer",
401
+ "minimum": 0
402
+ },
403
+ "expires": {
404
+ "type": "integer",
405
+ "minimum": 0
406
+ },
407
+ "deadLetterExchange": {
408
+ "type": "string"
409
+ },
410
+ "deadLetterRoutingKey": {
411
+ "type": "string"
412
+ },
413
+ "maxLength": {
414
+ "type": "integer",
415
+ "minimum": 0
416
+ },
417
+ "maxPriority": {
418
+ "type": "integer",
419
+ "minimum": 0
420
+ },
421
+ "arguments": {
422
+ "type": "object"
423
+ }
424
+ }
425
+ }
426
+ }
427
+ },
428
+ "binding": {
429
+ "type": "object",
430
+ "properties": {
431
+ "name": {
432
+ "type": "string"
433
+ },
434
+ "source": {
435
+ "type": "string"
436
+ },
437
+ "destination": {
438
+ "type": "string"
439
+ },
440
+ "destinationType": {
441
+ "type": "string",
442
+ "enum": ["queue", "exchange"]
443
+ },
444
+ "bindingKey": {
445
+ "type": "string"
446
+ },
447
+ "bindingKeys": {
448
+ "type": "array",
449
+ "items": {
450
+ "type": "string"
451
+ }
452
+ },
453
+ "qualifyBindingKeys": {
454
+ "type": "boolean"
455
+ },
456
+ "options": {
457
+ "type": "object"
458
+ }
459
+ }
460
+ },
461
+ "publication": {
462
+ "type": "object",
463
+ "properties": {
464
+ "name": {
465
+ "type": "string"
466
+ },
467
+ "vhost": {
468
+ "type": "string"
469
+ },
470
+ "exchange": {
471
+ "type": "string"
472
+ },
473
+ "queue": {
474
+ "type": "string"
475
+ },
476
+ "routingKey": {
477
+ "type": "string"
478
+ },
479
+ "confirm": {
480
+ "type": "boolean"
481
+ },
482
+ "timeout": {
483
+ "type": "integer",
484
+ "minimum": 0
485
+ },
486
+ "encryption": {
487
+ "type": "string"
488
+ },
489
+ "options": {
490
+ "type": "object",
491
+ "properties": {
492
+ "expiration": {
493
+ "type": "string"
494
+ },
495
+ "userId": {
496
+ "type": "string"
497
+ },
498
+ "CC": {
499
+ "oneOf": [
500
+ {
501
+ "type": "string"
502
+ },
503
+ {
504
+ "type": "array",
505
+ "items": {
506
+ "type": "string"
507
+ }
508
+ }
509
+ ]
510
+ },
511
+ "BCC": {
512
+ "oneOf": [
513
+ {
514
+ "type": "string"
515
+ },
516
+ {
517
+ "type": "array",
518
+ "items": {
519
+ "type": "string"
520
+ }
521
+ }
522
+ ]
523
+ },
524
+ "priority": {
525
+ "type": "integer",
526
+ "minimum": 0
527
+ },
528
+ "persistent": {
529
+ "type": "boolean"
530
+ },
531
+ "mandatory": {
532
+ "type": "boolean"
533
+ },
534
+ "contentType": {
535
+ "type": "string"
536
+ },
537
+ "contentEncoding": {
538
+ "type": "string"
539
+ },
540
+ "headers": {
541
+ "type": "object"
542
+ },
543
+ "replyTo": {
544
+ "type": "string"
545
+ },
546
+ "type": {
547
+ "type": "string"
548
+ },
549
+ "appId": {
550
+ "type": "string"
551
+ }
552
+ }
553
+ }
554
+ }
555
+ },
556
+ "subscription": {
557
+ "type": "object",
558
+ "properties": {
559
+ "name": {
560
+ "type": "string"
561
+ },
562
+ "vhost": {
563
+ "type": "string"
564
+ },
565
+ "queue": {
566
+ "type": "string"
567
+ },
568
+ "contentType": {
569
+ "type": "string"
570
+ },
571
+ "prefetch": {
572
+ "type": "integer",
573
+ "minimum": 0
574
+ },
575
+ "retry": {
576
+ "$ref": "#/definitions/retry"
577
+ },
578
+ "redeliveries": {
579
+ "properties": {
580
+ "limit": {
581
+ "type": "integer",
582
+ "minimum": 0
583
+ },
584
+ "timeout": {
585
+ "type": "integer",
586
+ "minimum": 0
587
+ },
588
+ "counter": {
589
+ "type": "string"
590
+ }
591
+ }
592
+ },
593
+ "closeTimeout": {
594
+ "type": "integer",
595
+ "minimum": 0
596
+ },
597
+ "encryption": {
598
+ "type": "string"
599
+ },
600
+ "promisifyAckOrNack": {
601
+ "type": "boolean"
602
+ },
603
+ "options": {
604
+ "type": "object",
605
+ "properties": {
606
+ "noAck": {
607
+ "type": "boolean"
608
+ },
609
+ "exclusive": {
610
+ "type": "boolean"
611
+ },
612
+ "priority": {
613
+ "type": "integer",
614
+ "minimum": 0
615
+ },
616
+ "arguments": {
617
+ "type": "object"
618
+ }
619
+ }
620
+ }
621
+ }
622
+ },
623
+ "shovel": {
624
+ "type": "object",
625
+ "properties": {
626
+ "name": {
627
+ "type": "string"
628
+ },
629
+ "subscription": {
630
+ "type": "string"
631
+ },
632
+ "publication": {
633
+ "type": "string"
634
+ }
635
+ }
636
+ },
637
+ "retry": {
638
+ "type": "object",
639
+ "properties": {
640
+ "min": {
641
+ "type": "integer",
642
+ "minimum": 0
643
+ },
644
+ "max": {
645
+ "type": "integer",
646
+ "minimum": 0
647
+ },
648
+ "factor": {
649
+ "type": "number",
650
+ "minimum": 0
651
+ },
652
+ "strategy": {
653
+ "type": "string",
654
+ "enum": ["exponential", "linear"]
655
+ }
656
+ }
657
+ },
658
+ "redeliveries": {
659
+ "type": "object",
660
+ "properties": {
661
+ "counters": {
662
+ "type": "object"
663
+ }
664
+ }
665
+ },
666
+ "encryption": {
667
+ "type": "object",
668
+ "properties": {
669
+ "key": {
670
+ "type": "string"
671
+ },
672
+ "algorithm": {
673
+ "type": "string"
674
+ },
675
+ "ivLength": {
676
+ "type": "integer",
677
+ "minimum": 1
678
+ }
679
+ }
680
+ }
681
+ }
682
+ }
@@ -0,0 +1,55 @@
1
+ const debug = require('debug')('rascal:management:client');
2
+ const format = require('util').format;
3
+ const _ = require('lodash');
4
+ const defaultAgent = require('superagent');
5
+
6
+ function Client(suppliedAgent) {
7
+ const agent = suppliedAgent || defaultAgent;
8
+ const self = this;
9
+
10
+ this.assertVhost = function (name, config, next) {
11
+ debug('Asserting vhost: %s', name);
12
+ const options = getVhostOptions(name, config);
13
+ self._request('put', options.url, options.timeout, (err) => {
14
+ if (!err) return next();
15
+ const message = err.status ? format('Failed to assert vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to assert vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
16
+ return next(new Error(message));
17
+ });
18
+ };
19
+
20
+ this.checkVhost = function (name, config, next) {
21
+ debug('Checking vhost: %s', name);
22
+ const options = getVhostOptions(name, config);
23
+ self._request('get', options.url, options.timeout, (err) => {
24
+ if (!err) return next();
25
+ const message = err.status ? format('Failed to check vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to check vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
26
+ return next(new Error(message));
27
+ });
28
+ };
29
+
30
+ this.deleteVhost = function (name, config, next) {
31
+ debug('Deleting vhost: %s', name);
32
+ const options = getVhostOptions(name, config);
33
+ self._request('delete', options.url, options.timeout, (err) => {
34
+ if (!err) return next();
35
+ const message = err.status ? format('Failed to delete vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to delete vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
36
+ return next(new Error(message));
37
+ });
38
+ };
39
+
40
+ this._request = function (method, url, timeout, next) {
41
+ agent[method](url)
42
+ .timeout({ deadline: timeout })
43
+ .then(() => {
44
+ next();
45
+ })
46
+ .catch(next);
47
+ };
48
+
49
+ function getVhostOptions(name, config) {
50
+ const url = format('%s/%s/%s', config.url, 'api/vhosts', name);
51
+ return _.defaultsDeep({ url }, config.options);
52
+ }
53
+ }
54
+
55
+ module.exports = Client;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rascal",
3
- "version": "14.0.0",
3
+ "version": "14.2.1",
4
4
  "description": "A config driven wrapper for amqplib supporting multi-host connections, automatic error recovery, redelivery flood protection, transparent encryption / decryption, channel pooling and publication timeouts",
5
5
  "main": "index.js",
6
6
  "dependencies": {
@@ -29,6 +29,7 @@
29
29
  "nyc": "^15.1.0",
30
30
  "prettier": "2.4.1",
31
31
  "random-readable": "^1.0.1",
32
+ "superagent-defaults": "^0.1.14",
32
33
  "zunit": "^3.0.8"
33
34
  },
34
35
  "peerDependencies": {
@@ -1,39 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- publicationChannelPools: {
5
- confirmPool: {
6
- max: 10,
7
- min: 10,
8
- evictionRunIntervalMillis: 1000,
9
- idleTimeoutMillis: 5000,
10
- autostart: true,
11
- },
12
- },
13
- connection: {
14
- heartbeat: 5,
15
- socketOptions: {
16
- timeout: 1000,
17
- },
18
- },
19
- exchanges: ['demo_ex'],
20
- queues: ['demo_q'],
21
- bindings: ['demo_ex[a.b.c] -> demo_q'],
22
- publications: {
23
- demo_pub: {
24
- exchange: 'demo_ex',
25
- routingKey: 'a.b.c',
26
- confirm: false,
27
- options: {
28
- persistent: false,
29
- },
30
- },
31
- },
32
- subscriptions: {
33
- demo_sub: {
34
- queue: 'demo_q',
35
- },
36
- },
37
- },
38
- },
39
- };
@@ -1,24 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- connection: {
5
- heartbeat: 1,
6
- socketOptions: {
7
- timeout: 1000,
8
- },
9
- },
10
- exchanges: [''],
11
- queues: ['demo_q'],
12
- publications: {
13
- demo_pub: {
14
- exchange: '',
15
- },
16
- },
17
- subscriptions: {
18
- demo_sub: {
19
- queue: 'demo_q',
20
- },
21
- },
22
- },
23
- },
24
- };
@@ -1,20 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- exchanges: ['demo_ex'],
5
- queues: ['demo_q'],
6
- bindings: ['demo_ex[a.b.c] -> demo_q'],
7
- publications: {
8
- demo_pub: {
9
- exchange: 'demo_ex',
10
- routingKey: 'a.b.c',
11
- },
12
- },
13
- subscriptions: {
14
- demo_sub: {
15
- queue: 'demo_q',
16
- },
17
- },
18
- },
19
- },
20
- };
@@ -1,26 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- connection: {
5
- heartbeat: 1,
6
- socketOptions: {
7
- timeout: 1000,
8
- },
9
- },
10
- exchanges: ['demo_ex'],
11
- queues: ['demo_q'],
12
- bindings: ['demo_ex[a.b.c] -> demo_q'],
13
- publications: {
14
- demo_pub: {
15
- exchange: 'demo_ex',
16
- routingKey: 'a.b.c',
17
- },
18
- },
19
- subscriptions: {
20
- demo_sub: {
21
- queue: 'demo_q',
22
- },
23
- },
24
- },
25
- },
26
- };
@@ -1,36 +0,0 @@
1
- module.exports = {
2
- vhosts: {
3
- '/': {
4
- publicationChannelPools: {
5
- confirmPool: {
6
- autostart: true,
7
- },
8
- },
9
- connection: {
10
- options: {
11
- heartbeat: 10,
12
- },
13
- socketOptions: {
14
- timeout: 1000,
15
- },
16
- },
17
- exchanges: ['demo_ex'],
18
- queues: ['demo_q'],
19
- bindings: ['demo_ex[a.b.c] -> demo_q'],
20
- publications: {
21
- demo_pub: {
22
- exchange: 'demo_ex',
23
- routingKey: 'a.b.c',
24
- options: {
25
- persistent: false,
26
- },
27
- },
28
- },
29
- subscriptions: {
30
- demo_sub: {
31
- queue: 'demo_q',
32
- },
33
- },
34
- },
35
- },
36
- };
@@ -1,54 +0,0 @@
1
- const debug = require('debug')('rascal:management:client');
2
- const format = require('util').format;
3
- const _ = require('lodash');
4
- const agent = require('superagent');
5
-
6
- function assertVhost(name, config, next) {
7
- debug('Asserting vhost: %s', name);
8
- const options = getVhostOptions(name, config);
9
- request('put', options.url, options.timeout, (err) => {
10
- if (!err) return next();
11
- const message = err.status ? format('Failed to assert vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to assert vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
12
- return next(new Error(message));
13
- });
14
- }
15
-
16
- function checkVhost(name, config, next) {
17
- debug('Checking vhost: %s', name);
18
- const options = getVhostOptions(name, config);
19
- request('get', options.url, options.timeout, (err) => {
20
- if (!err) return next();
21
- const message = err.status ? format('Failed to check vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to check vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
22
- return next(new Error(message));
23
- });
24
- }
25
-
26
- function deleteVhost(name, config, next) {
27
- debug('Deleting vhost: %s', name);
28
- const options = getVhostOptions(name, config);
29
- request('delete', options.url, options.timeout, (err) => {
30
- if (!err) return next();
31
- const message = err.status ? format('Failed to delete vhost: %s. %s returned status %d', name, config.loggableUrl, err.status) : format('Failed to delete vhost: %s. %s errored with: %s', name, config.loggableUrl, err.message);
32
- return next(new Error(message));
33
- });
34
- }
35
-
36
- function getVhostOptions(name, config) {
37
- const url = format('%s/%s/%s', config.url, 'api/vhosts', name);
38
- return _.defaultsDeep({ url }, config.options);
39
- }
40
-
41
- function request(method, url, timeout, next) {
42
- agent[method](url)
43
- .timeout({ deadline: timeout })
44
- .then(() => {
45
- next();
46
- })
47
- .catch(next);
48
- }
49
-
50
- module.exports = {
51
- assertVhost,
52
- checkVhost,
53
- deleteVhost,
54
- };