Skip to content

Commit

Permalink
feat: allow for a CircuitBreaker as a fallback
Browse files Browse the repository at this point in the history
If a CircuitBreaker is supplied as the fallback function, it will be
fired and the resulting Promise will be provided to any functions
listening for the 'fallback' event.
  • Loading branch information
lance committed Dec 22, 2016
1 parent e4a36f4 commit 85cbc34
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
8 changes: 7 additions & 1 deletion lib/circuit.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,13 @@ class CircuitBreaker extends EventEmitter {
* @return {@link CircuitBreaker} this
*/
fallback (func) {
this[FALLBACK_FUNCTION] = func;
let fb = func;
if (func instanceof CircuitBreaker) {
fb = function () {
return func.fire.apply(func, arguments);
};
}
this[FALLBACK_FUNCTION] = fb;
return this;
}

Expand Down
43 changes: 42 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,14 +366,55 @@ test('circuit halfOpen', (t) => {
});
});

test('CircuitBreaker fallback as a CircuitBreaker', (t) => {
t.plan(2);
const options = {
maxFailures: 1,
resetTimeout: 100
};

const input = -1;
const breaker = circuitBreaker(passFail, options);
breaker.fallback(circuitBreaker((x) => x, options));

breaker.on('fallback', (resultPromise) => {
resultPromise
.then((value) => t.equals(value, input, 'Fallback value equals input'))
.then(t.end);
});

breaker.fire(input)
.catch((e) => t.equals(e, 'Error: -1 is < 0', 'Breaker should fail'));
});

test('CircuitBreaker fallback as a CircuitBreaker that fails', (t) => {
t.plan(2);
const options = {
maxFailures: 1,
resetTimeout: 100
};

const input = -1;
const breaker = circuitBreaker(passFail, options);
breaker.fallback(circuitBreaker(passFail, options));

breaker.on('fallback', (resultPromise) => {
resultPromise
.catch((e) => t.equals(e, 'Error: -1 is < 0', 'Breaker should fail'))
.then(t.end);
});

breaker.fire(input)
.catch((e) => t.equals(e, 'Error: -1 is < 0', 'Breaker should fail'));
});
/**
* Returns a promise that resolves if the parameter
* 'x' evaluates to >= 0. Otherwise the returned promise fails.
*/
function passFail (x) {
return new Fidelity((resolve, reject) => {
setTimeout(() => {
(x >= 0) ? resolve(x) : reject(`Error: ${x} is < 0`);
(x > 0) ? resolve(x) : reject(`Error: ${x} is < 0`);
}, 100);
});
}
Expand Down

0 comments on commit 85cbc34

Please sign in to comment.