Comparing version 1.1.0 to 1.2.0
@@ -5,2 +5,20 @@ # Change Log | ||
<a name="1.2.0"></a> | ||
# [1.2.0](https://github.com/bucharest-gold/opossum/compare/v1.1.0...v1.2.0) (2017-06-20) | ||
### Bug Fixes | ||
* semaphore is part of the class ([0faa766](https://github.com/bucharest-gold/opossum/commit/0faa766)) | ||
* semaphore released with timeout ([e181d43](https://github.com/bucharest-gold/opossum/commit/e181d43)) | ||
### Features | ||
* implement our own semaphore ([4d0c057](https://github.com/bucharest-gold/opossum/commit/4d0c057)) | ||
* include semaphore rejects in hystrix stats ([2c326cc](https://github.com/bucharest-gold/opossum/commit/2c326cc)) | ||
* semaphore added ([e62a569](https://github.com/bucharest-gold/opossum/commit/e62a569)) | ||
<a name="1.1.0"></a> | ||
@@ -7,0 +25,0 @@ # [1.1.0](https://github.com/bucharest-gold/opossum/compare/v1.0.0...v1.1.0) (2017-06-06) |
@@ -6,2 +6,3 @@ 'use strict'; | ||
const HystrixStats = require('./hystrix-stats'); | ||
const Semaphore = require('./semaphore'); | ||
@@ -46,2 +47,5 @@ const STATE = Symbol('state'); | ||
* If they are disabled, all summary statistics (mean, percentiles) are returned as -1. | ||
* @param options.capacity the number of concurrent requests allowed. If the number of | ||
* currently executing function calls is equal to options.capacity, further calls to `fire()` | ||
* are rejected until at least one of the current requests completes. | ||
*/ | ||
@@ -55,2 +59,4 @@ class CircuitBreaker extends EventEmitter { | ||
this.options.rollingPercentilesEnabled = options.rollingPercentilesEnabled !== false; | ||
this.options.capacity = typeof options.capacity === 'number' ? options.capacity : 10; | ||
this.semaphore = new Semaphore(this.options.capacity); | ||
@@ -82,2 +88,3 @@ this[STATUS] = new Status(this.options); | ||
this.on('close', _ => this[STATUS].close()); | ||
this.on('semaphore-locked', increment('semaphoreRejections')); | ||
@@ -283,43 +290,55 @@ /** | ||
const latencyStartTime = Date.now(); | ||
timeout = setTimeout( | ||
() => { | ||
timeoutError = true; | ||
const error = new Error(`Timed out after ${this.options.timeout}ms`); | ||
error.code = 'ETIMEDOUT'; | ||
/** | ||
* Emitted when the circuit breaker action takes longer than `options.timeout` | ||
* @event CircuitBreaker#timeout | ||
*/ | ||
const latency = Date.now() - latencyStartTime; | ||
this.emit('timeout', error, latency); | ||
resolve(handleError(error, this, timeout, args, latency, resolve, reject)); | ||
}, this.options.timeout); | ||
if (this.semaphore.test()) { | ||
timeout = setTimeout( | ||
() => { | ||
timeoutError = true; | ||
const error = new Error(`Timed out after ${this.options.timeout}ms`); | ||
error.code = 'ETIMEDOUT'; | ||
/** | ||
* Emitted when the circuit breaker action takes longer than `options.timeout` | ||
* @event CircuitBreaker#timeout | ||
*/ | ||
const latency = Date.now() - latencyStartTime; | ||
this.semaphore.release(); | ||
this.emit('timeout', error, latency); | ||
resolve(handleError(error, this, timeout, args, latency, resolve, reject)); | ||
}, this.options.timeout); | ||
try { | ||
const result = this.action.apply(this.action, args); | ||
const promise = (typeof result.then === 'function') | ||
? result | ||
: Promise.resolve(result); | ||
try { | ||
const result = this.action.apply(this.action, args); | ||
const promise = (typeof result.then === 'function') | ||
? result | ||
: Promise.resolve(result); | ||
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); | ||
promise.then((result) => { | ||
if (!timeoutError) { | ||
clearTimeout(timeout); | ||
/** | ||
* Emitted when the circuit breaker action succeeds | ||
* @event CircuitBreaker#success | ||
*/ | ||
this.emit('success', result, (Date.now() - latencyStartTime)); | ||
this.semaphore.release(); | ||
resolve(result); | ||
if (this.options.cache) { | ||
CACHE.set(this, promise); | ||
} | ||
} | ||
} | ||
}) | ||
.catch((error) => { | ||
const latencyEndTime = Date.now() - latencyStartTime; | ||
handleError(error, this, timeout, args, latencyEndTime, resolve, reject); | ||
}); | ||
} catch (error) { | ||
}) | ||
.catch((error) => { | ||
this.semaphore.release(); | ||
const latencyEndTime = Date.now() - latencyStartTime; | ||
handleError(error, this, timeout, args, latencyEndTime, resolve, reject); | ||
}); | ||
} catch (error) { | ||
this.semaphore.release(); | ||
const latency = Date.now() - latencyStartTime; | ||
handleError(error, this, timeout, args, latency, resolve, reject); | ||
} | ||
} else { | ||
const latency = Date.now() - latencyStartTime; | ||
handleError(error, this, timeout, args, latency, resolve, reject); | ||
const err = new Error('Semaphore locked'); | ||
err.code = 'ESEMLOCKED'; | ||
this.emit('semaphore-locked', err, latency); | ||
handleError(err, this, timeout, args, latency, resolve, reject); | ||
} | ||
@@ -326,0 +345,0 @@ }); |
@@ -26,3 +26,3 @@ 'use strict'; | ||
json.rollingCountResponsesFromCache = stats.cacheHits; | ||
json.rollingCountSemaphoreRejected = stats.rejects; | ||
json.rollingCountSemaphoreRejected = stats.semaphoreRejections; | ||
json.rollingCountShortCircuited = stats.rejects; | ||
@@ -71,4 +71,4 @@ json.rollingCountSuccess = stats.successes; | ||
json.propertyValue_executionIsolationThreadPoolKeyOverride = null; | ||
json.propertyValue_executionIsolationSemaphoreMaxConcurrentRequests = 10; | ||
json.propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests = 10; | ||
json.propertyValue_executionIsolationSemaphoreMaxConcurrentRequests = stats.options.capacity; | ||
json.propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests = stats.options.capacity; | ||
json.propertyValue_metricsRollingStatisticalWindowInMilliseconds = 10000; | ||
@@ -75,0 +75,0 @@ json.propertyValue_requestCacheEnabled = stats.options.cache || false; |
@@ -167,2 +167,3 @@ 'use strict'; | ||
cacheMisses: 0, | ||
semaphoreRejections: 0, | ||
percentiles: {}, | ||
@@ -169,0 +170,0 @@ latencyTimes: [] |
{ | ||
"name": "opossum", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"author": "Red Hat, Inc.", | ||
@@ -75,4 +75,3 @@ "license": "Apache-2.0", | ||
"fail-fast" | ||
], | ||
"dependencies": {} | ||
] | ||
} |
@@ -153,2 +153,3 @@ # opossum | ||
* `fallback` - emitted when the breaker has a fallback function and executes it | ||
* `semaphore-locked` - emitted when the breaker is at capacity and cannot execute the request | ||
@@ -155,0 +156,0 @@ Handling events gives a greater level of control over your application behavior. |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
319783
14
6456
229