vulcain-corejs
Version:
Vulcain micro-service framework
92 lines (90 loc) • 3.19 kB
JavaScript
"use strict";
const actualTime_1 = require("../../utils/actualTime");
const commandMetricsFactory_1 = require("../metrics/commandMetricsFactory");
class NoOpCircuitBreaker {
constructor(commandKey, properties) {
this.commandKey = commandKey;
this.properties = properties;
}
allowRequest() { return true; }
markSuccess() { }
isOpen() { return false; }
}
class DefaultCircuitBreaker {
constructor(commandKey, properties) {
this.commandKey = commandKey;
this.properties = properties;
this.circuitOpen = false;
this.circuitOpenedOrLastTestedTime = actualTime_1.default.getCurrentTime();
}
allowRequest() {
if (this.properties.circuitBreakerForceOpen.value) {
return false;
}
if (this.properties.circuitBreakerForceClosed.value) {
this.isOpen();
return true;
}
return !this.isOpen() || this.allowSingleTest();
}
get metrics() {
return commandMetricsFactory_1.CommandMetricsFactory.getOrCreate(this.properties);
}
allowSingleTest() {
if (this.circuitOpen && actualTime_1.default.getCurrentTime() > this.circuitOpenedOrLastTestedTime + this.properties.circuitBreakerSleepWindowInMilliseconds.value) {
this.circuitOpenedOrLastTestedTime = actualTime_1.default.getCurrentTime();
return true;
}
else {
return false;
}
}
isOpen() {
if (this.circuitOpen) {
return true;
}
let { totalCount = 0, errorCount, errorPercentage } = this.metrics.getHealthCounts();
if (totalCount < this.properties.circuitBreakerRequestVolumeThreshold.value) {
return false;
}
if (errorPercentage > this.properties.circuitBreakerErrorThresholdPercentage.value) {
this.circuitOpen = true;
this.circuitOpenedOrLastTestedTime = actualTime_1.default.getCurrentTime();
return true;
}
else {
return false;
}
}
markSuccess() {
if (this.circuitOpen) {
this.circuitOpen = false;
this.metrics.reset();
}
}
}
const circuitBreakersByCommand = new Map();
class CircuitBreakerFactory {
static getOrCreate(properties) {
let previouslyCached = circuitBreakersByCommand.get(properties.commandName);
if (previouslyCached) {
return previouslyCached;
}
let circuitBreaker = properties.circuitBreakerEnabled ?
new DefaultCircuitBreaker(properties.commandName, properties) :
new NoOpCircuitBreaker(properties.commandName, properties);
circuitBreakersByCommand.set(properties.commandName, circuitBreaker);
return circuitBreakersByCommand.get(properties.commandName);
}
static get(commandName) {
return circuitBreakersByCommand.get(commandName);
}
static getCache() {
return circuitBreakersByCommand;
}
static resetCache() {
circuitBreakersByCommand.clear();
}
}
exports.CircuitBreakerFactory = CircuitBreakerFactory;
//# sourceMappingURL=circuitBreaker.js.map