Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | 1x 1x 1x 1x 1x 50x 50x 50x 50x 50x 49x 50x 50x 50x 50x 50x 50x 54x 54x 8x 54x 20x 20x 12x 12x 1x 29x 30x 9x 9x 9x 20x 20x 3x 2x 2x 18x 18x 1x 12x 12x 50x | const isObject = require('lodash.isobject')
const precond = require('precond')
const dependencyLevel = require('./dependency-level')
const HealthFactoryProvider = require('./health-strategies').HealthFactoryProvider
const ExponentialBackoffStrategy = require('./backoff-strategies').ExponentialBackoffStrategy
/**
* @class
* @classdesc Holds information about the health of a dependency, and executes strategies for
* checking a dependency's health
*/
class Dependency {
/**
* @param {Function} [backoffStrategy=ExponentialBackoffStrategy] The behaviour of the delay
* when re-checking a dependencys
* @param {Function} [healthStrategy=HttpStrategy] The strategy used to check a dependency's
* health
* @param {Enum} [level] A description of the reliance on this dependency
* @param {String} name The identifier to be used for a dependency
* @param {String} [url] The location where the dependency can be reached
*/
constructor ({ backoffStrategy, healthStrategy, level, name, url } = {}) {
precond.checkArgument(
isObject(backoffStrategy) && backoffStrategy.execute,
'backoffStrategy must be of type object and have a "execute" method'
)
precond.checkArgument(
isObject(healthStrategy) && healthStrategy.check,
'healthStrategy must be of type object and have a "check" method'
)
precond.checkArgument(
level === 'HARD' || level === 'SOFT',
'a dependency must either have a dependency level of HARD or soft'
)
precond.checkIsString(name, 'The dependency name must be a string')
if (url) {
precond.checkIsString(url, 'The dependency url must be a string')
}
this.backoffStrategy = backoffStrategy
this.healthStrategy = healthStrategy
this.level = level
this.healthy = true
this.name = name
this.url = url
}
/**
* @return {Object} A description of the dependency's health
*/
get healthSummary () {
/**
* Health information about a dependency
* Strategies may alter this summary to provide additional information
* @typedef {Object} Dependency~HealthInfo
* @property {String} name
* @property {Boolean} healthy
* @property {String} level
* @property {Date} lastChecked
*/
const summary = {
name: this.name,
healthy: this.healthy,
level: this.level,
lastChecked: this.lastChecked
}
if (this.healthStrategy.improveSummary) {
this.healthStrategy.improveSummary(summary, this.lastCheckResult)
}
return summary
}
/**
* Sets a dependency's status to healthy
*/
onHealthy () {
this.healthy = true
this.lastChecked = new Date()
}
/**
* Sets a dependency's status to unhealthy
*/
onUnhealthy () {
this.healthy = false
this.lastChecked = new Date()
}
/**
* Performs any cleanup needed
*/
cleanup () {
this.healthStrategy.cleanup()
}
/**
* @param {Integer} failAfter The number of times a dependency's health
* will be checked, before giving up
* @param {Integer} maxDelay The maximum interval of time to wait when retrying
* @return {Promise}
*/
check (retries = 1, maxDelay = 30000) {
// console.log('here', retries, maxDelay)
return this
.backoffStrategy
.execute({
func: () => this.healthStrategy.check(this.url),
retries,
maxDelay
})
.catch((e) => {
this.onUnhealthy()
this.lastCheckResult = undefined
return Promise.reject(this.healthSummary)
})
.then((result) => {
this.lastCheckResult = result
if (this.healthStrategy.areYouOk) {
if (!this.healthStrategy.areYouOk(result)) {
this.onUnhealthy()
return Promise.reject(this.healthSummary)
}
}
this.onHealthy()
return Promise.resolve(this.healthSummary)
})
}
}
module.exports = (injector) => {
const HealthStrategy = HealthFactoryProvider(injector)
/**
* @constructs Dependency
* @param {Object} opts Args for creating an instance of Dependency
*/
return ({
backoffStrategy = ExponentialBackoffStrategy({
retries: 3,
maxDelay: 0,
multiplier: 1000,
onSuccessEvt: 'healthy',
onFailureEvt: 'unhealthy'
}),
strategy = { type: 'http' },
level = dependencyLevel.SOFT,
name,
url
} = {}) => {
return new Dependency({
backoffStrategy,
healthStrategy: HealthStrategy(strategy),
level,
name,
url
})
}
}
|