diff --git a/.eslintrc.json b/.eslintrc.json index dbc8a5e..b6da684 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,7 +5,10 @@ }, "parserOptions": { "ecmaVersion": 8, - "sourceType": "module" + "sourceType": "module", + "ecmaFeatures": { + "experimentalObjectRestSpread": true + } }, "plugins": [ ], diff --git a/QueueService.js b/QueueService.js index 9d0e6f9..11e940a 100644 --- a/QueueService.js +++ b/QueueService.js @@ -98,24 +98,30 @@ QueueService.BatchQueueWorker = require('./BatchQueueWorker'); * Helper to generate a vhost config for Rascal based on old queue-name only setup * @param queueNames – Array of string queue names * @param [config] – Optional vhost config to append to + * @param {{exchangeDefaults:*, queueDefaults:*, bindingDefaults:*}} [options] – Additional options for exchanges, queues, and bindings * @returns {*|{exchanges: Array, queues: {}, bindings: {}, subscriptions: {}, publications: {}}} */ -QueueService.generateConfigFromQueueNames = (queueNames, config) => { +QueueService.generateConfigFromQueueNames = (queueNames, config, options={}) => { config = config || {}; - config.exchanges = config.exchanges || []; + config.exchanges = config.exchanges || {}; config.queues = config.queues || {}; config.bindings = config.bindings || {}; config.subscriptions = config.subscriptions || {}; config.publications = config.publications || {}; queueNames.forEach((name) => { - config.exchanges.push(name); - config.queues[name] = {}; + config.exchanges[name] = { + ...options.exchangeDefaults + }; + config.queues[name] = { + ...options.queueDefaults + }; config.bindings[name] = { + bindingKey: "", // typically defaults to #, does this matter? + destinationType: "queue", + ...options.bindingDefaults, source: name, destination: name, - destinationType: "queue", - bindingKey: "" // typically defaults to #, does this matter? }; config.subscriptions[name] = { queue: name }; config.publications[name] = { exchange: name }; diff --git a/README.md b/README.md index 29f5aed..3495906 100644 --- a/README.md +++ b/README.md @@ -304,6 +304,117 @@ Publishes a message to a Rascal publication. * `callback(err)` – (Optional) Function to fire when message has been sent or failed to send. * Returns a promise. + +## Static Methods + +### `QueueService.generateConfigFromQueueNames(queueNames, [config, [options]])` +Generates a QueueService config based on an array of queue names. +* `queueNames` – Array of string queue names +* `config` - Optional base configuration. Will be generated not given. + * `config.exchanges` – Exchanges container object + * `config.queues` – Queues container object + * `config.bindings` – Bindings container object + * `config.subscriptions` – Subscriptions container object + * `config.publications` – Publications container object +* `options` – Additional options when configuring exchanges, queues, and bindings + * `options.exchangeDefaults` - Options to set on the Rascal exchange configuration + * `options.queueDefaults` – Options to set on the Rascal queue configuration + * `options.bindingDefaults` – Options to set on the Rascal bindings configuration +Returns a usable configuration object for QueueService/Rascal + +For example: + +```js +const queueNames = ['queue1','queue2','queue3']; +const baseConfig = { + connections: [ + { + hostname: '127.0.0.1', + port: 1234, + user: 'username', + password: 'password', + options: { heartbeat: 1 }, + socketOptions: { timeout: 10000 }, + management: { url: 'http://username:password@127.0.0.1:1234' } + } + ] +}; +const configOptions = { + exchangeDefaults: { + assert: true, + type: 'direct' + } +}; +const config = { + rascal: { + vhosts: { + my_vhost: QueueService.generateConfigFromQueueNames(queueNames, baseConfig, configOptions) + } + } +}; +``` + +Is the same as: + +```js +config = { + rascal: { + vhosts: { + my_vhost: { + connections: [ + { + hostname: '127.0.0.1', + port: 1234, + user: 'username', + password: 'password', + options: { heartbeat: 1 }, + socketOptions: { timeout: 10000 }, + management: { url: 'http://username:password@127.0.0.1:1234' } + } + ], + exchanges: { + queue1: {assert: true, type: 'direct'}, + queue2: {assert: true, type: 'direct'}, + queue3: {assert: true, type: 'direct'} + }, + queues: {queue1: {}, queue2: {}, queue3: {}}, + bindings: { + queue1: { + bindingKey: '', + destinationType: 'queue', + source: 'queue1', + destination: 'queue1' + }, + queue2: { + bindingKey: '', + destinationType: 'queue', + source: 'queue2', + destination: 'queue2' + }, + queue3: { + bindingKey: '', + destinationType: 'queue', + source: 'queue3', + destination: 'queue3' + } + }, + subscriptions: { + queue1: {queue: 'queue1'}, + queue2: {queue: 'queue2'}, + queue3: {queue: 'queue3'} + }, + publications: { + queue1: {exchange: 'queue1'}, + queue2: {exchange: 'queue2'}, + queue3: {exchange: 'queue3'} + } + } + } + } +}; +``` + + ## Events This class does not emit events. diff --git a/package.json b/package.json index c5982b2..65c2487 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "okanjo-app-queue", - "version": "2.0.0", + "version": "2.1.0", "description": "Service for interfacing with RabbitMQ", "main": "QueueService.js", "scripts": { diff --git a/test/QueueService.test.js b/test/QueueService.test.js index 93b4868..91d3daa 100644 --- a/test/QueueService.test.js +++ b/test/QueueService.test.js @@ -135,7 +135,7 @@ describe('QueueService', () => { const config = QueueService.generateConfigFromQueueNames(queues); config.should.deepEqual({ - exchanges: ['apples', 'bananas', 'cherries'], + exchanges: {apples: {}, bananas: {}, cherries: {}}, queues: {apples: {}, bananas: {}, cherries: {}}, bindings: { apples: { @@ -206,7 +206,7 @@ describe('QueueService', () => { } } ], - exchanges: ['apples', 'bananas', 'cherries'], + exchanges: {apples: {}, bananas: {}, cherries: {}}, queues: {apples: {}, bananas: {}, cherries: {}}, bindings: { apples: { @@ -242,5 +242,111 @@ describe('QueueService', () => { }); + it('can generate with all the options', () => { + + const queueNames = ['queue1','queue2','queue3']; + const baseConfig = { + connections: [ + { + hostname: '127.0.0.1', + port: 1234, + user: 'username', + password: 'password', + options: { + heartbeat: 1 + }, + socketOptions: { + timeout: 10000 + }, + management: { + url: 'http://username:password@127.0.0.1:1234' + } + } + ] + }; + const configOptions = { + exchangeDefaults: { + assert: true, + type: 'direct' + }, + queueDefaults: { + durable: true + }, + bindingDefaults: { + bananas: 1 + } + }; + const config = { + rascal: { + vhosts: { + my_vhost: QueueService.generateConfigFromQueueNames(queueNames, baseConfig, configOptions) + } + } + }; + config.should.deepEqual({ + rascal: { + vhosts: { + my_vhost: { + connections: [ + { + hostname: '127.0.0.1', + port: 1234, + user: 'username', + password: 'password', + options: { heartbeat: 1 }, + socketOptions: { timeout: 10000 }, + management: { url: 'http://username:password@127.0.0.1:1234' } + } + ], + exchanges: { + queue1: { assert: true, type: 'direct' }, + queue2: { assert: true, type: 'direct' }, + queue3: { assert: true, type: 'direct' } + }, + queues: { + queue1: { durable: true }, + queue2: { durable: true }, + queue3: { durable: true } + }, + bindings: { + queue1: { + bindingKey: '', + destinationType: 'queue', + bananas: 1, + source: 'queue1', + destination: 'queue1' + }, + queue2: { + bindingKey: '', + destinationType: 'queue', + bananas: 1, + source: 'queue2', + destination: 'queue2' + }, + queue3: { + bindingKey: '', + destinationType: 'queue', + bananas: 1, + source: 'queue3', + destination: 'queue3' + } + }, + subscriptions: { + queue1: { queue: 'queue1' }, + queue2: { queue: 'queue2' }, + queue3: { queue: 'queue3' } + }, + publications: { + queue1: { exchange: 'queue1' }, + queue2: { exchange: 'queue2' }, + queue3: { exchange: 'queue3' } + } + } + } + } + }); + + }); + }); }); \ No newline at end of file