Flexible, fault-tolerant operations for Typescript.
- Node
>=4.6.0
- Typescript
>=2.0
- Experimental decorators
- ES6 target (for async/await support)
npm install node-endeavour --save
import endeavour from 'node-endeavour'
function unreliable () {
if (Math.random <= 0.25) return Promise.resolve()
return Promise.reject()
}
// create a fault tolerant operation. This will be retried
// 10 times, backing off exponentially with no maximum delay.
const faultTolerant = endeavour(unreliable)
async function main () {
let result
try {
result = await faultTolerant()
} catch (error) {
console.log(error)
}
}
main()
Creates a new EndeavourRunnable
; a wrapped version of your function that will retry indefinitely, or up until some specified limit. The default options are as follows:
-
retries
The maximum amount of times to retry the operation. Defaults to10
. -
constant
The base in exponential backoff, or the slope in linear backoff. Defaults to2
. -
minTimeout
The number of milliseconds before starting the first retry. Default is1000
. -
maxTimeout
The maximum number of milliseconds between two retries. Default isInfinity
.
You may also specify this
(useful for wrapping instance methods).
class Thing {
doSomethingUnreliable () {}
}
const instance = new Thing()
const faultTolerant = endeavour(instance.doSomethingUnreliable, instance)
faultTolerant()
.then(res => { console.log('yay!') })
.catch(e => { console.log(':(')) })
See the decorators section for a more terse way of handling these cases.
Using your wrapped function from endeavour(...)
works much in the same way as before. Arguments are be passed like this:
myFaultTolerantOperation(['some', 'arguments'])
The wrapped operation also accepts and optional function to allow for greater control over how retries should proceed.
faultTolerantOperation((result, next) => {
if (result.error instanceof MyCustomError) {
return next(new Error('something went horribly wrong :('))
}
})
Calling next()
with an error will stop your operation. You can also pass in an new array of arguments for subsequent retries.
faultTolerantOperation((result, next) => {
if (result.error instanceof MyCustomError) {
return next(['new', 'args'])
}
})
You could also just inspect the result of the last attempt.
faultTolerantOperation(result => {
console.log(result.error)
})
A decorator for providing metadata about how retriable methods in a class should operate. Takes the options defined here.
Provides the same functionality as endeavour, but for class methods.
@endeavourable({ retries: 15 })
class {
// retried 15 times
@endeavourify()
unreliableMethod () {
if (Math.random <= 0.25) return Promise.resolve()
return Promise.reject()
}
// retried 5 times
@endeavourify({ retries: 5 })
doSomething () { }
// retried 10 times
@endeavourify()
otherThing() { }
}
When no arguments are given to @endeavourable
or @endeavourify
, the defaults provided here will be used.
Want something for plain old JS? Check out node-retry.