rascal 15.0.0 → 16.0.0

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,15 @@
1
1
  # Change Log
2
2
 
3
+ ## 16.0.0
4
+
5
+ - Automatically set replyTo message property when a publication references a replyTo queue
6
+ - Stop prefixing binding keys with replyTo uuid
7
+ - Drop support for Node 12
8
+
9
+ ## 15.0.1
10
+
11
+ - Fix MaxListenersExceeded warning when there are more than 10 vhosts - See https://github.com/guidesmiths/rascal/issues/206
12
+
3
13
  ## 15.0.0
4
14
 
5
15
  - Drop support for Node 10
package/README.md CHANGED
@@ -30,6 +30,7 @@ Rascal seeks to either solve these problems, make them easier to deal with or br
30
30
  - Transparent encryption / decryption
31
31
  - Automatic reconnection and resubscription
32
32
  - Advanced error handling including delayed, limited retries
33
+ - RPC Support
33
34
  - Redelivery protection
34
35
  - Channel pooling
35
36
  - Flow control
@@ -679,6 +680,25 @@ Enable to purge the queue during initialisation. Useful when running automated t
679
680
  }
680
681
  ```
681
682
 
683
+ ##### replyTo
684
+
685
+ Sometimes you want to publish a message, and have the consumer of the message send a reply to the same application instance that published the original message. This can be difficult if you application is deployed using multiple instances which share a common configuration. Quite often the solution is to make your application stateless so it doesn't matter which instance receives the reply. An altnernative is to mark the queue as a reply queue using the replyTo.
686
+
687
+ ```json
688
+ {
689
+ "queues": {
690
+ "q1": {
691
+ "replyTo": true
692
+ }
693
+ },
694
+ "publications": {
695
+ "replyTo": "q1"
696
+ }
697
+ }
698
+ ```
699
+
700
+ When true, Rascal will append a uuid to the queue name so that it is unique for each instance of the application. Use this conjunction with the publication replyTo property, to automaticlaly set the replyTo property on outbound messages to the unique queue name. You may also want to make make the queue non durable and exclusive too (see below).
701
+
682
702
  ##### options
683
703
 
684
704
  Define any further configuration in an options block
@@ -37,6 +37,7 @@ function Publication(vhost, borrowChannelFn, returnChannelFn, destroyChannelFn,
37
37
  const content = getContent(payload);
38
38
  publishConfig.options.contentType = publishConfig.options.contentType || content.type;
39
39
  publishConfig.options.messageId = publishConfig.options.messageId || uuid();
40
+ publishConfig.options.replyTo = publishConfig.options.replyTo || publishConfig.replyTo;
40
41
 
41
42
  publishConfig.encryption ? _publishEncrypted(content.buffer, publishConfig, next) : _publish(content.buffer, publishConfig, next);
42
43
  };
@@ -6,6 +6,8 @@ const Vhost = require('../Vhost');
6
6
 
7
7
  module.exports = _.curry((config, ctx, next) => {
8
8
  ctx.vhosts = {};
9
+ const maxListeners = Math.max(ctx.broker.getMaxListeners(), Object.keys(config.vhosts).length);
10
+ ctx.broker.setMaxListeners(maxListeners);
9
11
  async.eachSeries(
10
12
  _.values(config.vhosts),
11
13
  (vhostConfig, callback) => {
@@ -133,11 +133,11 @@ module.exports = _.curry((rascalConfig, next) => {
133
133
  },
134
134
  {}
135
135
  );
136
-
137
136
  _.each(_.defaults({}, publications, defaultPublications), configurePublication);
138
137
  }
139
138
 
140
139
  function configurePublication(publicationConfig, name) {
140
+ if (publicationConfig.destination) return;
141
141
  debug('Configuring publication: %s', name);
142
142
  if (rascalConfig.publications[name] && rascalConfig.publications[name].vhost !== publicationConfig.vhost) throw new Error(format('Duplicate publication: %s', name));
143
143
  rascalConfig.publications[name] = _.defaultsDeep(publicationConfig, { name }, rascalConfig.defaults.publications);
@@ -145,6 +145,13 @@ module.exports = _.curry((rascalConfig, next) => {
145
145
  const destination = Object.prototype.hasOwnProperty.call(publicationConfig, 'exchange') ? rascalConfig.vhosts[publicationConfig.vhost].exchanges[publicationConfig.exchange] : rascalConfig.vhosts[publicationConfig.vhost].queues[publicationConfig.queue];
146
146
  rascalConfig.publications[name].destination = destination.fullyQualifiedName;
147
147
 
148
+ if (publicationConfig.replyTo) {
149
+ const replyToQueue = rascalConfig.vhosts[publicationConfig.vhost].queues[publicationConfig.replyTo];
150
+
151
+ if (!replyToQueue) throw new Error(`Publication: ${name} refers to an unknown reply queue: ${publicationConfig.replyTo}`);
152
+ publicationConfig.replyTo = replyToQueue.fullyQualifiedName;
153
+ }
154
+
148
155
  if (publicationConfig.encryption && _.isString(publicationConfig.encryption)) {
149
156
  rascalConfig.publications[name].encryption = _.defaultsDeep({ name: publicationConfig.encryption }, rascalConfig.encryption[publicationConfig.encryption]);
150
157
  }
@@ -260,10 +267,6 @@ module.exports = _.curry((rascalConfig, next) => {
260
267
  if (bindingConfig.qualifyBindingKeys) {
261
268
  config.bindings[name].bindingKey = fqn.qualify(bindingConfig.bindingKey, config.namespace);
262
269
  }
263
- if (bindingConfig.destinationType === 'queue') {
264
- const queue = config.queues[bindingConfig.destination];
265
- config.bindings[name].bindingKey = fqn.prefix(queue && queue.replyTo, bindingConfig.bindingKey, '.');
266
- }
267
270
  });
268
271
  }
269
272
 
@@ -101,7 +101,7 @@ module.exports = _.curry((config, next) => {
101
101
  }
102
102
 
103
103
  function validatePublication(publication, publicationName) {
104
- validateAttributes('Publication', publication, publicationName, ['name', 'vhost', 'exchange', 'queue', 'routingKey', 'confirm', 'options', 'destination', 'autoCreated', 'deprecated', 'encryption', 'timeout']);
104
+ validateAttributes('Publication', publication, publicationName, ['name', 'vhost', 'exchange', 'queue', 'routingKey', 'confirm', 'options', 'destination', 'autoCreated', 'deprecated', 'encryption', 'replyTo', 'timeout']);
105
105
  if (!publication.vhost) throw new Error(format('Publication: %s is missing a vhost', publicationName));
106
106
  if (!(Object.prototype.hasOwnProperty.call(publication, 'exchange') || publication.queue)) throw new Error(format('Publication: %s is missing an exchange or a queue', publicationName));
107
107
  if (Object.prototype.hasOwnProperty.call(publication, 'exchange') && publication.queue) throw new Error(format('Publication: %s has an exchange and a queue', publicationName));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rascal",
3
- "version": "15.0.0",
3
+ "version": "16.0.0",
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": {
@@ -30,13 +30,13 @@
30
30
  "prettier": "^2.4.1",
31
31
  "random-readable": "^1.0.1",
32
32
  "superagent-defaults": "^0.1.14",
33
- "zunit": "^3.2.1"
33
+ "zunit": "^4.0.0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "amqplib": ">=0.5.5"
37
37
  },
38
38
  "engines": {
39
- "node": ">=12.0.0"
39
+ "node": ">=14"
40
40
  },
41
41
  "scripts": {
42
42
  "test": "zUnit",