Comparing version 1.3.0 to 2.0.0
14
index.js
@@ -9,4 +9,4 @@ const ms = require('ms'); | ||
arity: 'auto', | ||
monitor: () => {}, | ||
trigger: (err) => true | ||
onTrip: () => {}, | ||
trigger: () => true | ||
}; | ||
@@ -36,3 +36,3 @@ | ||
var failures, lastFailure, currentCooldown, monitorCalled; | ||
var failures, lastFailure, currentCooldown; | ||
@@ -55,3 +55,2 @@ function getState() { | ||
currentCooldown = config.cooldown; | ||
monitorCalled = false; | ||
} | ||
@@ -72,6 +71,2 @@ | ||
const err = new DisyuntorError(`${config.name}: the circuit-breaker is open`); | ||
if (!monitorCalled) { | ||
monitorCalled = true; | ||
config.monitor({err}); | ||
} | ||
return setImmediate(originalCallback, err); | ||
@@ -86,2 +81,5 @@ } else if (currentState === states[2]) { | ||
lastFailure = Date.now(); | ||
if (failures >= config.maxFailures) { | ||
config.onTrip(err, failures, currentCooldown); | ||
} | ||
} | ||
@@ -88,0 +86,0 @@ originalCallback(err); |
{ | ||
"name": "disyuntor", | ||
"description": "A circuit-breaker implementation with exponential backoff.", | ||
"version": "1.3.0", | ||
"version": "2.0.0", | ||
"author": "José F. Romaniello <jfromaniello@gmail.com> (http://joseoncode.com)", | ||
@@ -6,0 +6,0 @@ "repository": { |
@@ -46,3 +46,3 @@ A [circuit-breaker](http://martinfowler.com/bliki/CircuitBreaker.html) implementation for node.js with exponential backoff. | ||
//optionally log errors | ||
monitor: (details) => logger.panic({ err: details.err, args: details.args }, 'Error on dns.lookup') | ||
onTrip: (err, failures, cooldown) => console.log(`dns.lookup triped ${failures} times because ${err.message}! There will be no more attempts for ${cooldown}ms.`) | ||
}); | ||
@@ -49,0 +49,0 @@ |
@@ -7,3 +7,3 @@ const disyuntor = require('./..'); | ||
describe('disyuntor (promise)', function () { | ||
describe('promise interface', function () { | ||
@@ -36,20 +36,19 @@ it('should throw an error if func is undefined', function () { | ||
maxCooldown: 400, | ||
monitor: details => monitorCalls.push(details) | ||
onTrip: (err, failures, cooldown) => monitorCalls.push({err, failures, cooldown}) | ||
}); | ||
}); | ||
it('should fail with timeout', function (done) { | ||
var startTime = Date.now(); | ||
sut().catch(err => { | ||
it('should fail with timeout', function () { | ||
const startTime = Date.now(); | ||
return sut().catch(err => { | ||
assert.match(err.message, /test\.func: specified timeout of 10ms was reached/); | ||
assert.closeTo(Date.now() - startTime, 10, 10); | ||
assert.equal(monitorCalls.length, 0); | ||
done(); | ||
assert.equal(monitorCalls.length, 1); | ||
}); | ||
}); | ||
it('should fail immediately after "maxFailures"', function (done) { | ||
sut().catch(() => { | ||
var startTime = Date.now(); | ||
sut().catch(err => { | ||
it('should fail immediately after "maxFailures"', function () { | ||
return sut().catch((originalError) => { | ||
const startTime = Date.now(); | ||
return sut().catch(err => { | ||
assert.instanceOf(err, Error); | ||
@@ -59,4 +58,3 @@ assert.instanceOf(err, DisyuntorError); | ||
assert.closeTo(Date.now() - startTime, 1, 2); | ||
assert.equal(monitorCalls[0].err, err); | ||
done(); | ||
assert.equal(monitorCalls[0].err, originalError); | ||
}); | ||
@@ -71,3 +69,3 @@ }); | ||
assert.match(err.message, /test\.func: specified timeout of 10ms was reached/); | ||
assert.equal(monitorCalls.length, 0); | ||
assert.equal(monitorCalls.length, 2); | ||
done(); | ||
@@ -145,3 +143,3 @@ }); | ||
cooldown: 200, | ||
monitor: details => monitorCalls.push(details) | ||
onTrip: (err, failures, cooldown) => monitorCalls.push({ err, failures, cooldown }) | ||
}); | ||
@@ -154,6 +152,6 @@ }); | ||
assert.equal(err1.message, 'failure'); | ||
assert.equal(monitorCalls.length, 0); | ||
assert.equal(monitorCalls.length, 1); | ||
return sut(2).catch(err2 => { | ||
assert.match(err2.message, /test\.func: the circuit-breaker is open/); | ||
assert.equal(monitorCalls[0].err, err2); | ||
assert.equal(monitorCalls[0].err, err1); | ||
}); | ||
@@ -160,0 +158,0 @@ }); |
@@ -5,3 +5,2 @@ const disyuntor = require('./..'); | ||
describe('disyuntor', function () { | ||
@@ -16,7 +15,7 @@ | ||
describe('when the protected function doesnt call back', function () { | ||
var monitorCalls = []; | ||
var tripCalls = []; | ||
var sut; | ||
beforeEach(function () { | ||
monitorCalls = []; | ||
tripCalls = []; | ||
sut = disyuntor(cb => setTimeout(cb, 500), { | ||
@@ -28,3 +27,3 @@ name: 'test.func', | ||
maxCooldown: 400, | ||
monitor: details => monitorCalls.push(details) | ||
onTrip: (err, failures, cooldown) => tripCalls.push({err, failures, cooldown}), | ||
}); | ||
@@ -38,3 +37,3 @@ }); | ||
assert.closeTo(Date.now() - startTime, 10, 10); | ||
assert.equal(monitorCalls.length, 0); | ||
assert.equal(tripCalls.length, 1); | ||
done(); | ||
@@ -45,3 +44,3 @@ }); | ||
it('should fail immediately after "maxFailures"', function (done) { | ||
sut(() => { | ||
sut((originalError) => { | ||
var startTime = Date.now(); | ||
@@ -51,3 +50,3 @@ sut(err => { | ||
assert.closeTo(Date.now() - startTime, 1, 2); | ||
assert.equal(monitorCalls[0].err, err); | ||
assert.equal(tripCalls[0].err, originalError); | ||
done(); | ||
@@ -63,3 +62,3 @@ }); | ||
assert.match(err.message, /test\.func: specified timeout of 10ms was reached/); | ||
assert.equal(monitorCalls.length, 0); | ||
assert.equal(tripCalls.length, 2); | ||
done(); | ||
@@ -95,3 +94,3 @@ }); | ||
assert.match(err.message, /test\.func: specified timeout of 10ms was reached/); | ||
assert.equal(monitorCalls.length, 0); | ||
assert.equal(tripCalls.length, 2); | ||
cb(); | ||
@@ -106,3 +105,3 @@ }); | ||
assert.match(err.message, /test\.func: the circuit-breaker is open/); | ||
assert.equal(monitorCalls.length, 1); | ||
assert.equal(tripCalls.length, 2); | ||
cb(); | ||
@@ -116,3 +115,3 @@ }); | ||
assert.match(err.message, /test\.func: specified timeout of 10ms was reached/); | ||
assert.equal(monitorCalls.length, 1); | ||
assert.equal(tripCalls.length, 3); | ||
cb(); | ||
@@ -127,3 +126,3 @@ }); | ||
assert.match(err.message, /test\.func: specified timeout of 10ms was reached/); | ||
assert.equal(monitorCalls.length, 1); | ||
assert.equal(tripCalls.length, 4); | ||
cb(); | ||
@@ -141,3 +140,3 @@ }); | ||
describe('when the protected function fails', function () { | ||
var monitorCalls = []; | ||
var tripCalls = []; | ||
var sut; | ||
@@ -147,3 +146,3 @@ var fail = false; | ||
beforeEach(function () { | ||
monitorCalls = []; | ||
tripCalls = []; | ||
fail = false; | ||
@@ -158,3 +157,3 @@ sut = disyuntor((i, callback) => { | ||
cooldown: 200, | ||
monitor: details => monitorCalls.push(details) | ||
onTrip: (err, failures, cooldown) => tripCalls.push({err, failures, cooldown}), | ||
}); | ||
@@ -167,6 +166,6 @@ }); | ||
assert.equal(err1.message, 'failure'); | ||
assert.equal(monitorCalls.length, 0); | ||
assert.equal(tripCalls.length, 1); | ||
sut(2, err2 => { | ||
assert.match(err2.message, /test\.func: the circuit-breaker is open/); | ||
assert.equal(monitorCalls[0].err, err2); | ||
assert.equal(tripCalls[0].err, err1); | ||
done(); | ||
@@ -173,0 +172,0 @@ }); |
22318
523