Skip to content

Commit

Permalink
Refactor rabbit-config to a separate library
Browse files Browse the repository at this point in the history
  • Loading branch information
beeman committed Aug 2, 2016
1 parent 5a9ad60 commit e48a862
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 29 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# loopback-component-mq
Loopback Component for working with a Message Queue

[![Circle CI](https://circleci.com/gh/fullcube/loopback-component-mq.svg?style=svg)](https://circleci.com/gh/fullcube/loopback-component-mq) [![Dependencies](http://img.shields.io/david/fullcube/loopback-component-mq.svg?style=flat)](https://david-dm.org/fullcube/loopback-component-mq) [![Coverage Status](https://coveralls.io/repos/github/fullcube/loopback-component-mq/badge.svg?branch=master)](https://coveralls.io/github/fullcube/loopback-component-mq?branch=master)

## Installation

Expand Down
17 changes: 9 additions & 8 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const _ = require('lodash')
const debug = require('debug')('loopback:component:mq')
const RabbitConfig = require('./rabbit-config')
const Rabbit = require('./rabbit')
let rabbit = null
let msqQueue = null

Expand All @@ -15,16 +15,17 @@ function setupQueueConsumer(app, queue, definition) {
const modelName = definition.model
const methodName = definition.method
const Model = app.models[modelName]
const Method = Model[methodName]

// Check if the model exists
if (!Model) {
throw new Error(`setupQueueConsumer: Model not found ${modelName}`)
throw new Error(`setupQueueConsumer: Model not found: ${modelName}`)
}

const Method = Model[methodName]

// Check if the method on the model exists
if (!Method) {
throw new Error(`setupQueueConsumer: Method not found ${modelName}.${methodName}`)
console.warn(`setupQueueConsumer: Method not found: ${modelName}.${methodName}`) // eslint-disable-line no-console
}

// Start consuming the queue
Expand All @@ -39,7 +40,7 @@ function setupQueueProducer(app, queue, definition) {
const Model = app.models[modelName]

if (!Model) {
throw new Error(`setupQueueProducer: Model not found ${modelName}`)
throw new Error(`setupQueueProducer: Model not found: ${modelName}`)
}

debug('setupQueueProducer: queue: %s, model: %s, method: %s', queue, modelName, methodName)
Expand All @@ -50,8 +51,8 @@ function setupQueueProducer(app, queue, definition) {
}

module.exports = function loopbackComponentMq(app, config) {
const options = config.options
const topology = config.topology
const options = config.options || {}
const topology = config.topology || {}

debug('options: %o', options)
debug('topology: %o', topology)
Expand All @@ -68,7 +69,7 @@ module.exports = function loopbackComponentMq(app, config) {
ds = { settings: {} }
}

rabbit = new RabbitConfig(ds.settings.options || {})
rabbit = new Rabbit(ds.settings.options || {})

// Loop through all the defined queues
_.forEach(topology, (handlers, queue) => {
Expand Down
36 changes: 15 additions & 21 deletions lib/rabbit-config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@

const AmqpStats = require('amqp-stats')
require('ssl-root-cas').inject()
const https = require('https')
const jackrabbit = require('jackrabbit')
const querystring = require('querystring')

require('ssl-root-cas').inject()
const cas = https.globalAgent.options.ca || []

module.exports = function rabbitConfig(settings) {

// Build up config object
Expand All @@ -20,13 +16,8 @@ module.exports = function rabbitConfig(settings) {
protocol: settings.protocol || 'amqp',
}

if (settings.sslKey) {
// Add our SSL cert to the registry
cas.push(settings.sslKey.replace(/\\n/g, '\n'))
}

// Define a connection config for jackrabbit
const jackrabbitConnectionConfig = {
const jackrabbitConnection = {
username: config.username,
password: config.password,
hostname: config.hostname,
Expand All @@ -36,25 +27,28 @@ module.exports = function rabbitConfig(settings) {
}

// Define a the SSL config for jackrabbit
const jackrabbitSslConfig = {
const cas = https.globalAgent.options.ca || []

// Optionally add SSL cert to the registry
if (settings.sslKey) {
cas.push(settings.sslKey.replace(/\\n/g, '\n'))
}

const jackrabbitSsl = {
ca: cas,
}

// Define a connection object for ampq-stats
const amqpStatsConfig = {
// Define a connection object for amqp-stats
const amqpStats = {
username: config.username,
password: config.password,
hostname: `${config.hostname}:${config.restPort}`,
protocol: (config.protocol === 'amqps') ? 'https' : 'http',
}

const rabbit = jackrabbit(jackrabbitConnectionConfig, jackrabbitSslConfig)
const exchange = rabbit.default()
const stats = new AmqpStats(amqpStatsConfig)

return {
rabbit,
exchange,
stats,
jackrabbitConnection,
jackrabbitSsl,
amqpStats,
}
}
21 changes: 21 additions & 0 deletions lib/rabbit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

const AmqpStats = require('amqp-stats')
const jackrabbit = require('jackrabbit')
const RabbitConfig = require('./rabbit-config')

module.exports = function rabbitFn(settings) {

// Build up config object
const config = RabbitConfig(settings)

// Initialize libraries
const rabbit = jackrabbit(config.jackrabbitConnection, config.jackrabbitSsl)
const exchange = rabbit.default()
const stats = new AmqpStats(config.amqpStats)

return {
rabbit,
exchange,
stats,
}
}
118 changes: 118 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const expect = chai.expect
const TEST_APP = path.join(__dirname, 'test-server')
const app = require(path.join(TEST_APP, 'server/server.js'))
const Event = app.models.Event
const RabbitConfig = require('../lib/rabbit-config')
const Component = require('../lib/index')

describe('Component initialized', function() {

Expand All @@ -34,4 +36,120 @@ describe('Component initialized', function() {
})
})

it('should be able to run the method defined in the component configuration of the test-server', function() {
app.models.Event.sendOutgoingMessage()
})

})

describe('Rapid config with SSL key', function() {

it('should initialize the config', function() {
const cfg = {
hostname: 'localhost',
sslKey: '123'
}
const rabbit = new RabbitConfig(cfg)
expect(rabbit.jackrabbitConnection).to.deep.equal({ username: 'guest',
password: 'guest',
hostname: 'localhost',
port: '5672',
protocol: 'amqp',
vhost: '%2F',
})
expect(rabbit.amqpStats).to.deep.equal({
username: 'guest',
password: 'guest',
hostname: 'localhost:15672',
protocol: 'http',
})
})
})

describe('Main component config', function() {

it('should initialize with a default dataSource value', function() {
const cfg = {}
const component = new Component(app, cfg)
expect(component).to.be.an('object')
})

it('should initialize with a non-existing dataSource value', function() {
const cfg = {
options: {
dataSource: 'i-do-not-exist'
}
}
const component = new Component(app, cfg)
expect(component).to.be.an('object')
})

it('should throw an error with a non-existing producer Model value', function() {
const cfg = {
options: {
dataSource: 'rabbit'
},
topology: {
'my-queue-name': {
producer: {
model: 'Unknown'
}
}
}
}
try {
const component = new Component(app, cfg)
}
catch (err) {
expect(err).to.be.an('error')
expect(err.message).to.equal('setupQueueProducer: Model not found: Unknown')
}
})

it('should throw an error with a non-existing consumer Model value', function() {
const cfg = {
options: {
dataSource: 'rabbit'
},
topology: {
'my-queue-name': {
consumer: {
model: 'Unknown',
}
}
}
}
try {
const component = new Component(app, cfg)
}
catch (err) {
expect(err).to.be.an('error')
expect(err.message).to.equal('setupQueueConsumer: Model not found: Unknown')
}
})


it('should throw an error with a non-existing consumer Method value', function() {
const cfg = {
options: {
dataSource: 'rabbit'
},
topology: {
'my-queue-name': {
consumer: {
model: 'Event',
method: 'nonExisting',
}
}
}
}
try {
const component = new Component(app, cfg)
}
catch (err) {
expect(err).to.be.an('error')
expect(err.message).to.equal('setupQueueConsumer: Method not found: Event.nonExisting')
}
})

})

0 comments on commit e48a862

Please sign in to comment.