Skip to content

Commit a2bfe3c

Browse files
committed
feat: improve testability, and test coverage
1 parent 3546021 commit a2bfe3c

File tree

14 files changed

+603
-110
lines changed

14 files changed

+603
-110
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
config.*json
22
log/*
3+
*.log
34
node_modules/
4-
coverage/
5+
coverage/
6+
scripts/

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
const QueueHandler = require('./lib/app')
2-
module.exports = QueueHandler()
1+
const QueueHandler = require('./lib/queue-handler')
2+
module.exports = new QueueHandler()

lib/broker.js

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,29 @@
11
'use strict'
22

3-
const conf = require('../config')
3+
/**
4+
* Message Broker
5+
*/
6+
const config = require('../config')
47
const errs = require('./errors')
58
const Rsmq = require('rsmq-worker')
69
const Throttle = require('./throttle')
710

811
/**
9-
* Message Broker
10-
* Polls the queue server for messages, builds requests
12+
* @constructor
13+
* @classdesc Polls the queue server for messages, builds requests
1114
* for the app and handles errors
12-
* @param {function} app - the function to call when a message is received
15+
* @param {QueueHandler} queueHandler - the function to call when a message is received
1316
*/
14-
var Broker = function (app) {
15-
// get config options
16-
var opts = conf.get('broker')
17-
18-
// instantiate message queue
19-
this.rsmq = new Rsmq(opts.queue)
17+
var Broker = function (queueHandler) {
18+
var opts = config.get('broker')
2019

21-
// instantiate throttle
22-
var throttle = new Throttle(opts.throttle, (start, stop) => {
23-
if (start) {
24-
this.rsmq.start()
25-
}
26-
27-
if (stop) {
28-
this.rsmq.stop()
29-
}
30-
})
20+
this.queueHandler = queueHandler
21+
this.rsmq = this.initialiseQueue(opts)
22+
this.throttle = this.initialiseThrottle(opts)
3123

3224
// message received
3325
this.rsmq.on('message', (msg, next) => {
34-
throttle.more()
26+
this.throttle.more()
3527
next(false) // next message but don't delete
3628
})
3729

@@ -51,54 +43,67 @@ var Broker = function (app) {
5143
}
5244

5345
// call the app and delete message on success
54-
console.log('Broker calling app')
55-
app.handle(null, req, (err) => {
56-
console.log('response from app')
57-
if (processResponse(req, err)) {
46+
this.queueHandler.handle(null, req, (err) => {
47+
if (this.processResponse(req, err)) {
5848
this.rsmq.del(msg.id)
5949
}
6050

61-
throttle.less()
51+
this.throttle.less()
6252
})
53+
})
6354

64-
// done if no error and no retries remaining
65-
function processResponse (req, err) {
66-
var queueError
55+
// queue error
56+
this.rsmq.on('error', (err, msg) => {
57+
this.queueHandler.handle(new errs.BrokerError(err, msg.message))
58+
})
6759

68-
if (err) {
69-
queueError = new errs.WorkerError(err, req.message)
70-
}
60+
// start listening
61+
return this.rsmq.start()
62+
}
7163

72-
if (err && !req.retries) {
73-
queueError = new errs.ExceededError(req.message)
74-
}
64+
/**
65+
* done if no error and no retries remaining
66+
*/
67+
Broker.prototype.processResponse = function (req, err) {
68+
var queueError
7569

76-
if (!req.address.length) {
77-
queueError = new errs.InvalidError(req.message)
78-
}
70+
if (err) {
71+
queueError = new errs.WorkerError(err, req.message)
72+
}
7973

80-
if (Date.now() / 1000 > req.timeout) {
81-
queueError = new errs.TimeoutError(req.message)
82-
}
74+
if (err && !req.retries) {
75+
queueError = new errs.ExceededError(req.message)
76+
}
8377

84-
if (queueError) {
85-
app.handle(queueError)
86-
}
78+
if (!req.address.length) {
79+
queueError = new errs.InvalidError(req.message)
80+
}
8781

88-
return !err || !req.retries
89-
}
90-
})
82+
if (Date.now() / 1000 > req.timeout) {
83+
queueError = new errs.TimeoutError(req.message)
84+
}
9185

92-
// queue error
93-
this.rsmq.on('error', (err, msg) => {
94-
console.log(err)
95-
app(new errs.BrokerError(err, msg.message))
96-
})
86+
if (queueError) {
87+
this.queueHandler.handle(queueError)
88+
}
9789

98-
// start listening
99-
return this.rsmq.start()
90+
return !err || !req.retries
10091
}
10192

102-
module.exports = function (app) {
103-
return new Broker(app)
93+
Broker.prototype.initialiseQueue = function (options) {
94+
return new Rsmq(options.queue)
10495
}
96+
97+
Broker.prototype.initialiseThrottle = function (options) {
98+
return new Throttle(options.throttle, (start, stop) => {
99+
if (start) {
100+
this.rsmq.start()
101+
}
102+
103+
if (stop) {
104+
this.rsmq.stop()
105+
}
106+
})
107+
}
108+
109+
module.exports = Broker

lib/loader.js

Lines changed: 0 additions & 33 deletions
This file was deleted.

lib/logger.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
'use strict'
22

3-
const conf = require('../config')
4-
const logger = require('@dadi/logger')
5-
logger.init(conf.get('logging'), null, conf.get('env'))
3+
/**
4+
* Logger
5+
*/
6+
var config = require('../config')
7+
var logger = require('@dadi/logger')
8+
logger.init(config.get('logging'), null, config.get('env'))
69

710
module.exports = logger

lib/app.js renamed to lib/queue-handler.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
'use strict'
22

3+
/**
4+
* QueueHandler
5+
*/
36
const logger = require('./logger')
47
const Broker = require('./broker')
58
const router = require('./router')()
69

710
/**
8-
* Main App
9-
* Starts the message broker, delegates messages to
11+
* @constructor
12+
* @classdesc Starts the message broker, delegates messages to
1013
* workers via the router, and handles errors
1114
*/
1215
var QueueHandler = function () {
@@ -22,6 +25,4 @@ QueueHandler.prototype.handle = function (err, req, done) {
2225
}
2326
}
2427

25-
module.exports = function () {
26-
return new QueueHandler()
27-
}
28+
module.exports = QueueHandler

lib/router.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
'use strict'
22

3-
const logger = require('./logger')
3+
/**
4+
* Router
5+
*/
6+
var config = require('../config')
7+
var logger = require('./logger')
8+
var Workers = require('./workers')
49

510
/**
6-
* Message Router
11+
* @constructor
712
*/
813
var Router = function () {
9-
this.workers = require('./loader')
14+
this.workers = new Workers().load(config.get('workers.path'))
1015
}
1116

1217
/**

lib/throttle.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1-
/*
2-
* Message Throttle -
3-
* Stops the message broker when it hits max
1+
/**
2+
* Throttle
3+
*/
4+
5+
/**
6+
* @constructor
7+
* @classdesc Stops the message broker when it hits max
48
* Restarts when below max
5-
* Takes an 'engine' callback with (stop, start) params
9+
* @param {number} max -
10+
* @param {function} engine - a callback function accepting two Boolean arguments, `start` and `stop`
611
*/
7-
812
var Throttle = function (max, engine) {
913
this.max = max
1014
this.engine = engine
1115
this.val = 0
1216
}
1317

18+
/**
19+
*
20+
*/
1421
Throttle.prototype.adjust = function (amt) {
1522
var adj = this.val + amt
1623

@@ -24,10 +31,16 @@ Throttle.prototype.adjust = function (amt) {
2431
}
2532
}
2633

34+
/**
35+
*
36+
*/
2737
Throttle.prototype.less = function () {
2838
this.adjust(-1)
2939
}
3040

41+
/**
42+
*
43+
*/
3144
Throttle.prototype.more = function () {
3245
this.adjust(1)
3346
}

lib/workers.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
'use strict'
2+
3+
/**
4+
* Workers
5+
*/
6+
var fs = require('fs')
7+
var path = require('path')
8+
9+
/**
10+
* @constructor
11+
* @classdesc Loads worker functions into an object literal
12+
*/
13+
var Workers = function () {
14+
15+
}
16+
17+
/**
18+
* @param {string} root - xx
19+
* @returns {Array} workers - xx
20+
*/
21+
Workers.prototype.load = function (root) {
22+
this.workers = {}
23+
24+
// files must be read before directories so that deeper levels can be
25+
// assigned as properties to the initial worker functions
26+
fs.readdirSync(root).forEach(fileName => this.loadPath(root, fileName, 'file'))
27+
fs.readdirSync(root).forEach(fileName => this.loadPath(root, fileName, 'dir'))
28+
29+
return this.workers
30+
}
31+
32+
/**
33+
* @param {string} root - xx
34+
* @param {string} fileName - xx
35+
* @param {string} type - xx
36+
*/
37+
Workers.prototype.loadPath = function (root, fileName, type) {
38+
var filePath = path.join(root, fileName)
39+
var isDir = fs.lstatSync(filePath).isDirectory()
40+
var basename = path.basename(filePath, '.js')
41+
42+
if (type === 'file' && path.extname(filePath) === '.js') {
43+
this.workers[basename] = require(path.resolve(filePath))
44+
}
45+
46+
if (type === 'dir' && isDir) { // recurse
47+
this.workers[basename] = Object.assign(this.workers[basename] || {}, this.load(filePath))
48+
}
49+
}
50+
51+
module.exports = function () {
52+
return new Workers()
53+
}

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"description": "A lightweight, high-performance task queue built on Node JS and Redis. Includes a broker for queue management and routing, plus a worker framework for processing messages.",
55
"main": "index.js",
66
"scripts": {
7-
"test": "standard 'lib/*.js' && env NODE_ENV=test ./node_modules/.bin/istanbul cover --report cobertura --report text --report html --report lcov ./node_modules/mocha/bin/_mocha",
7+
"docs": "jsdoc -c ./docs/conf.json -t ./node_modules/ink-docstrap/template -R README.md -r lib -d docs",
8+
"test": "snazzy 'lib/*.js' && env NODE_ENV=test ./node_modules/.bin/istanbul cover --report cobertura --report text --report html --report lcov ./node_modules/mocha/bin/_mocha && npm run docs",
89
"posttest": "./scripts/coverage.js",
910
"start": "node ./index.js --node-env=development"
1011
},
@@ -17,12 +18,14 @@
1718
"babel-register": "^6.18.0",
1819
"env-test": "^1.0.0",
1920
"fakeredis": "^1.0.3",
21+
"ink-docstrap": "^1.3.0",
2022
"istanbul": "^1.1.0-alpha.1",
2123
"istanbul-cobertura-badger": "^1.2.1",
2224
"mocha": "^3.2.0",
2325
"redis": "^2.6.4",
2426
"should": "^11.1.2",
2527
"sinon": "^1.17.7",
28+
"snazzy": "^5.0.0",
2629
"standard": "^8.6.0",
2730
"supertest": "^2.0.1"
2831
},

0 commit comments

Comments
 (0)