Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

opossum

Package Overview
Dependencies
Maintainers
1
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

opossum - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

18

CHANGELOG.md

@@ -5,2 +5,20 @@ # Change Log

<a name="1.1.0"></a>
# [1.1.0](https://github.com/bucharest-gold/opossum/compare/v1.0.0...v1.1.0) (2017-06-06)
### Bug Fixes
* don't let circuits get stuck half open ([5e1171c](https://github.com/bucharest-gold/opossum/commit/5e1171c))
* fix logic around pendingClose ([4d89ae4](https://github.com/bucharest-gold/opossum/commit/4d89ae4))
### Features
* add ETIMEDOUT error code for timeout error ([#64](https://github.com/bucharest-gold/opossum/issues/64)) ([5df9f65](https://github.com/bucharest-gold/opossum/commit/5df9f65))
* addition of rolling percentile latency's. GH-ISSUE [#38](https://github.com/bucharest-gold/opossum/issues/38) ([ce7b50d](https://github.com/bucharest-gold/opossum/commit/ce7b50d))
* remove fidelity promises. ([3f5827a](https://github.com/bucharest-gold/opossum/commit/3f5827a))
<a name="1.0.0"></a>

@@ -7,0 +25,0 @@ # [1.0.0](https://github.com/bucharest-gold/opossum/compare/v0.6.0...v1.0.0) (2017-04-06)

7

index.js

@@ -5,3 +5,2 @@ (() => {

const CircuitBreaker = require('./lib/circuit');
const Fidelity = require('fidelity');

@@ -11,4 +10,3 @@ const defaults = {

errorThresholdPercentage: 50,
resetTimeout: 30000, // 30 seconds
Promise: Fidelity
resetTimeout: 30000 // 30 seconds
};

@@ -30,5 +28,2 @@

* the breaker to `halfOpen` state, and trying the action again.
* @param options.Promise {Promise} Opossum uses Fidelity promises, but works
* fine with any Promise that follows the spec. You can specify your favored
* implementation by providing the constructor as an option.
* @return a {@link CircuitBreaker} instance

@@ -35,0 +30,0 @@ */

@@ -42,2 +42,5 @@ 'use strict';

* @param options.name the name to use for this circuit when reporting stats
* @param options.rollingPercentilesEnabled {boolean} This property indicates whether execution latencies
* should be tracked and calculated as percentiles.
* If they are disabled, all summary statistics (mean, percentiles) are returned as -1.
*/

@@ -50,3 +53,3 @@ class CircuitBreaker extends EventEmitter {

this.options.rollingCountBuckets = options.rollingCountBuckets || 10;
this.Promise = options.Promise;
this.options.rollingPercentilesEnabled = options.rollingPercentilesEnabled !== false;

@@ -61,3 +64,3 @@ this[STATUS] = new Status(this.options);

if (typeof action !== 'function') {
this.action = _ => this.Promise.resolve(action);
this.action = _ => Promise.resolve(action);
} else this.action = action;

@@ -67,3 +70,3 @@

const increment = property => _ => this[STATUS].increment(property);
const increment = property => (result, runTime) => this[STATUS].increment(property, runTime);

@@ -91,2 +94,3 @@ this.on('success', increment('successes'));

circuit[STATE] = HALF_OPEN;
circuit[PENDING_CLOSE] = true;
circuit.emit('halfOpen', circuit.options.resetTimeout);

@@ -101,3 +105,3 @@ }, circuit.options.resetTimeout);

this.on('open', _startTimer(this));
this.on('success', () => this.close());
this.on('success', _ => this.close());
if (this.options.cache) {

@@ -157,2 +161,6 @@ CACHE.set(this, undefined);

get pendingClose () {
return this[PENDING_CLOSE];
}
/**

@@ -262,3 +270,3 @@ * True if the circuit is currently closed. False otherwise.

if (this.opened || (this.halfOpen && this[PENDING_CLOSE])) {
if (this.opened && !this.pendingClose) {
/**

@@ -270,10 +278,11 @@ * Emitted when the circuit breaker is open and failing fast

return fallback(this, 'Breaker is open', args) ||
return fallback(this, 'Breaker is open', args, 0) ||
Promise.reject(new Error('Breaker is open'));
}
this[PENDING_CLOSE] = this.halfOpen;
this[PENDING_CLOSE] = false;
let timeout;
let timeoutError = false;
return new this.Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
const latencyStartTime = Date.now();
timeout = setTimeout(

@@ -283,2 +292,3 @@ () => {

const error = new Error(`Timed out after ${this.options.timeout}ms`);
error.code = 'ETIMEDOUT';
/**

@@ -288,4 +298,5 @@ * Emitted when the circuit breaker action takes longer than `options.timeout`

*/
this.emit('timeout', error);
resolve(fallback(this, error, args) || fail(this, error, args));
const latency = Date.now() - latencyStartTime;
this.emit('timeout', error, latency);
resolve(handleError(error, this, timeout, args, latency, resolve, reject));
}, this.options.timeout);

@@ -297,23 +308,25 @@

? result
: this.Promise.resolve(result);
: Promise.resolve(result);
promise
.then((result) => {
if (!timeoutError) {
/**
* Emitted when the circuit breaker action succeeds
* @event CircuitBreaker#success
*/
this.emit('success', result);
resolve(result);
if (this.options.cache) {
CACHE.set(this, promise);
}
clearTimeout(timeout);
promise.then((result) => {
if (!timeoutError) {
clearTimeout(timeout);
/**
* Emitted when the circuit breaker action succeeds
* @event CircuitBreaker#success
*/
this.emit('success', result, (Date.now() - latencyStartTime));
resolve(result);
if (this.options.cache) {
CACHE.set(this, promise);
}
})
.catch((error) =>
handleError(error, this, timeout, args, resolve, reject));
}
})
.catch((error) => {
const latencyEndTime = Date.now() - latencyStartTime;
handleError(error, this, timeout, args, latencyEndTime, resolve, reject);
});
} catch (error) {
handleError(error, this, timeout, args, resolve, reject);
const latency = Date.now() - latencyStartTime;
handleError(error, this, timeout, args, latency, resolve, reject);
}

@@ -331,6 +344,6 @@ });

function handleError (error, circuit, timeout, args, resolve, reject) {
function handleError (error, circuit, timeout, args, latency, resolve, reject) {
clearTimeout(timeout);
fail(circuit, error, args);
const fb = fallback(circuit, error, args);
fail(circuit, error, args, latency);
const fb = fallback(circuit, error, args, latency);
if (fb) resolve(fb);

@@ -342,3 +355,3 @@ else reject(error);

if (circuit[FALLBACK_FUNCTION]) {
return new circuit.Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
const result = circuit[FALLBACK_FUNCTION].apply(circuit[FALLBACK_FUNCTION], args);

@@ -355,3 +368,3 @@ /**

function fail (circuit, err, args) {
function fail (circuit, err, args, latency) {
/**

@@ -361,3 +374,3 @@ * Emitted when the circuit breaker action fails

*/
circuit.emit('failure', err);
circuit.emit('failure', err, latency);

@@ -371,4 +384,2 @@ // check stats to see if the circuit should be opened

}
return circuit.Promise.reject.apply(null, [err]);
}

@@ -375,0 +386,0 @@

@@ -34,16 +34,27 @@ 'use strict';

// TODO: caluclate these latency values
json.latencyExecute_mean = 0;
json.latencyExecute_mean = stats.latencyMean || 0;
json.latencyExecute = {
'0': 0,
'25': 0,
'50': 0,
'75': 0,
'90': 0,
'95': 0,
'99': 0,
'99.5': 0,
'100': 0
0: stats.percentiles['0'],
25: stats.percentiles['0.25'],
50: stats.percentiles['0.5'],
75: stats.percentiles['0.75'],
90: stats.percentiles['0.9'],
95: stats.percentiles['0.95'],
99: stats.percentiles['0.99'],
99.5: stats.percentiles['0.995'],
100: stats.percentiles['1']
};
json.latencyTotal_mean = 0;
json.latencyTotal = { '0': 0, '25': 0, '50': 0, '75': 0, '90': 0, '95': 0, '99': 0, '99.5': 0, '100': 0 };
// Whats the difference between execute and total?
json.latencyTotal_mean = stats.latencyMean;
json.latencyTotal = {
0: stats.percentiles['0'],
25: stats.percentiles['0.25'],
50: stats.percentiles['0.5'],
75: stats.percentiles['0.75'],
90: stats.percentiles['0.9'],
95: stats.percentiles['0.95'],
99: stats.percentiles['0.99'],
99.5: stats.percentiles['0.995'],
100: stats.percentiles['1']
};
json.propertyValue_circuitBreakerRequestVolumeThreshold = 5;

@@ -50,0 +61,0 @@ json.propertyValue_circuitBreakerSleepWindowInMilliseconds = stats.options.resetTimeout;

'use strict';
const Fidelity = require('fidelity');
module.exports = exports = function promisify (func) {
return function promisifiedFunction () {
return new Fidelity((resolve, reject) => {
return new Promise((resolve, reject) => {
const cb = (err, result) => {

@@ -9,0 +7,0 @@ if (err) reject(err);

@@ -6,2 +6,3 @@ 'use strict';

const TIMEOUT = Symbol('timeout');
const PERCENTILES = Symbol('percentiles');

@@ -64,3 +65,7 @@ const EventEmitter = require('events').EventEmitter;

this[WINDOW] = new Array(this[BUCKETS]);
this[PERCENTILES] = [0.0, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99, 0.995, 1];
// Default this value to true
this.rollingPercentilesEnabled = options.rollingPercentilesEnabled;
// prime the window with buckets

@@ -86,8 +91,41 @@ for (let i = 0; i < this[BUCKETS]; i++) this[WINDOW][i] = bucket();

get stats () {
return this[WINDOW].reduce((acc, val) => {
const totals = this[WINDOW].reduce((acc, val) => {
// the window starts with all but one bucket undefined
if (!val) return acc;
Object.keys(acc).forEach(key => (acc[key] += val[key] || 0));
Object.keys(acc).forEach(key => {
if (key !== 'latencyTimes' && key !== 'percentiles') {
(acc[key] += val[key] || 0);
}
});
if (this.rollingPercentilesEnabled) {
acc.latencyTimes.push.apply(acc.latencyTimes, val.latencyTimes || []);
}
return acc;
}, bucket());
if (this.rollingPercentilesEnabled) {
// Sort the latencyTimess
totals.latencyTimes.sort((a, b) => a - b);
// Get the mean latency
// Mean = sum of all values in the array/length of array
if (totals.latencyTimes.length) {
totals.latencyMean = (totals.latencyTimes.reduce((a, b) => a + b, 0)) / totals.latencyTimes.length;
} else {
totals.latencyMean = 0;
}
// Calculate Percentiles
this[PERCENTILES].forEach(percentile => {
totals.percentiles[percentile] = calculatePercentile(percentile, totals.latencyTimes);
});
} else {
totals.latencyMean = -1;
this[PERCENTILES].forEach(percentile => {
totals.percentiles[percentile] = -1;
});
}
return totals;
}

@@ -102,4 +140,7 @@

increment (property) {
increment (property, latencyRunTime) {
this[WINDOW][0][property]++;
if (property === 'successes' || property === 'failures' || property === 'timeouts') {
this[WINDOW][0].latencyTimes.push(latencyRunTime || 0);
}
}

@@ -129,5 +170,15 @@

cacheHits: 0,
cacheMisses: 0
cacheMisses: 0,
percentiles: {},
latencyTimes: []
});
function calculatePercentile (percentile, arr) {
if (percentile === 0) {
return arr[0] || 0;
}
const idx = Math.ceil(percentile * arr.length);
return arr[idx - 1] || 0;
}
module.exports = exports = Status;
{
"name": "opossum",
"version": "1.0.0",
"version": "1.1.0",
"author": "Red Hat, Inc.",

@@ -46,14 +46,16 @@ "license": "Apache-2.0",

"babel-plugin-transform-mangle-names": "~2.1.2",
"babel-plugin-transform-merge-sibling-variables": "6.8.2",
"babel-plugin-transform-merge-sibling-variables": "6.8.3",
"babel-plugin-transform-minify-booleans": "~6.8.0",
"babel-plugin-transform-undefined-to-void": "~6.8.0",
"browserify": "~14.1.0",
"browserify": "~14.3.0",
"escompress": "~0.5.0",
"eslint": "~3.19.0",
"eslint-config-semistandard": "~7.0.0",
"eslint-config-standard": "~7.0.0",
"eslint-plugin-react": "~6.10.0",
"eslint-config-semistandard": "~11.0.0",
"eslint-config-standard": "~10.2.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-node": "^5.0.0",
"eslint-plugin-promise": "~3.5.0",
"eslint-plugin-standard": "~2.1.0",
"http-server": "~0.9.0",
"eslint-plugin-react": "~7.0.0",
"eslint-plugin-standard": "~3.0.1",
"http-server": "~0.10.0",
"ink-docstrap": "~1.3.0",

@@ -75,5 +77,3 @@ "istanbul": "~0.4.5",

],
"dependencies": {
"fidelity": "~4.2.0"
}
"dependencies": {}
}

@@ -23,3 +23,3 @@ # opossum

| Issue tracker: | https://github.com/bucharest-gold/opossum/issues |
| Engines: | Node.js 4.x, 5.x, 6.x, 7.x
| Engines: | Node.js 4.x, 6.x, 8.x

@@ -222,16 +222,2 @@ ## Usage

### Promise Interoperability
The `Promise` implementation used in `opossum` is compliant with both the
ES6 `Promise` API as well as the `promises/A+` API. This means that it doesn't
matter what flavor of promise your API uses, `opossum` should work fine with
it. If you would like to control what `Promise` implementation used in
`opossum`, provide a `Promise` constructor function in your options when
you create the breaker. E.g.
```javascript
// Force opossum to use native JS promises
const breaker = circuitBreaker(readFile, { Promise: Promise });
```
### Hystrix Metrics

@@ -238,0 +224,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc