Skip to content

Instantly share code, notes, and snippets.

@marekpiechut
Last active January 30, 2017 14:38
Show Gist options
  • Save marekpiechut/03890e1d40fa17c487406b424843e9ae to your computer and use it in GitHub Desktop.
Save marekpiechut/03890e1d40fa17c487406b424843e9ae to your computer and use it in GitHub Desktop.
Simple circuit breaker in ES6 (available in NPM as simple-circuit-breaker)
const CLOSED = Symbol('CLOSED')
const OPEN = Symbol('OPEN')
const HALF_OPEN = Symbol('HALF_OPEN')
const MSG = 'Functionality disabled due to previous errors.'
module.exports = (asyncFn, gracePeriodMs = 3000, threshold = 1, message = MSG) => {
let state = CLOSED
let failures = 0
let openedAt
function handleSuccess(value) {
if(state !== CLOSED) {
state = CLOSED
failures = 0
}
return value
}
function handleFailure(error) {
if(state === HALF_OPEN || state === CLOSED) {
failures += 1
if(failures >= threshold) {
state = OPEN
openedAt = Date.now()
}
}
throw error
}
function tryReset() {
if(state === OPEN && openedAt && Date.now() - openedAt > gracePeriodMs) {
state = HALF_OPEN
return true
}
}
return function () {
if(state === CLOSED || state === HALF_OPEN || tryReset()) {
return asyncFn.apply(asyncFn.this, arguments).then(handleSuccess, handleFailure)
} else {
return Promise.reject(new Error(message))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment