all files / hystrix-too-busy/ index.js

100% Statements 50/50
100% Branches 26/26
100% Functions 5/5
100% Lines 50/50
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                                                        15×     15×     13×           16× 16×     16× 16×     16×         16×                       13× 13× 13×   13×   13×       13×           13×   13×   13×      
'use strict';
 
const Hystrix = require('hystrixjs');
 
const commandFactory = Hystrix.commandFactory;
const circuitFactory = Hystrix.circuitFactory;
const metricsFactory = Hystrix.metricsFactory;
 
const GROUP = 'TooBusyGroup';
const PREFIX = 'too-busy-';
 
const toobusy = require('toobusy-js');
Object.assign(module.exports, toobusy);
 
const DEFAULT_CONFIG = {
    circuitBreakerErrorThresholdPercentage: 50, // optional
    circuitBreakerForceClosed: false, // optional
    circuitBreakerForceOpened: false, // optional
    circuitBreakerRequestVolumeThreshold: 20, // optional
    circuitBreakerSleepWindowInMilliseconds: 5000, // optional
    requestVolumeRejectionThreshold: 0, // optional
    statisticalWindowNumberOfBuckets: 10, // optional
    statisticalWindowLength: 10000, // optional
    percentileWindowNumberOfBuckets: 6, // optional
    percentileWindowLength: 60000 // optional
};
 
let tooBusyConfig = {
    default: DEFAULT_CONFIG
};
 
/*
  Too busy module lacks a floating window of observations over time which leads to false positives for
  too busy signal.
  By using hystrix we get a flowting monitor window which should eliminate false positives.
  The tresholds are controlled by hsyrtix command configuration.
  Now it will emit tooBusy only when the system accumulated many of them
*/
module.exports.getStatus = function getStatus(name, callback) {
    if (arguments.length === 1) {
        callback = name;
        name = undefined;
    }
 
    getCommand(name)
    .execute()
    .then(() => callback(false))
    .catch(err => {
        if (err.message === 'OpenCircuitError') {
            return callback(true);
        }
        // otherwise we are all good and supress too busy error
        callback(false);
    });
};
 
function getCommand(name) {
    const commandName = PREFIX + (name || 'hystrix-command');
    const builder = commandFactory
    .getOrCreate(commandName, GROUP);
 
    const commandConfig = tooBusyConfig.commands && tooBusyConfig.commands[name];
    builder.config = commandConfig ||
        tooBusyConfig.default;
 
    builder.run(function run() {
        return new Promise((resolve, reject) => {
            if (module.exports.deps.toobusy()) {
                return reject(new Error('TooBusy'));
            }
            resolve();
        });
    });
 
    return builder.build();
}
 
// expose for easy testing
module.exports.deps = {
    Hystrix: Hystrix,
    toobusy: toobusy
};
 
Object.defineProperty(module.exports, 'command', {
    get: function () {
        return getCommand();
    }
});
 
module.exports.init = function init(config) {
    commandFactory.resetCache();
    circuitFactory.resetCache();
    metricsFactory.resetCache();
 
    config = config || {};
 
    if (config.default) {
        tooBusyConfig.default = Object.assign(tooBusyConfig.default,
            config.default);
    }
 
    if (config.commands) {
        tooBusyConfig.commands = tooBusyConfig.commands || {};
        Object.keys(config.commands).forEach(name => {
            tooBusyConfig.commands[name] =
                Object.assign({}, tooBusyConfig.default,
                    config.commands[name]);
        });
    }
 
    if (config.latencyThreshold) {
        module.exports.maxLag(config.latencyThreshold);
    }
    if (config.interval) {
        module.exports.interval(config.interval);
    }
    if (config.smoothingFactor) {
        module.exports.smoothingFactor(config.smoothingFactor);
    }
};