diff --git a/docs/index.html b/docs/index.html index 7b32d951..558767c4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,7 +2,7 @@
-2.1.0
2.2.0
String
:
- the metrics for all circuits
+ the metrics for all circuits or
+undefined if no circuits have been created
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Get an Iterator
object containing all
+circuits that have been created but not subsequently shut down.
Iterator
:
+ an
+
+Iterator
+
+ of all available circuits
@@ -1358,6 +1441,70 @@ Gets a Set iterator of all active circuits. If a circuit +has been created, but subsequently shut down, it will not +be included in the Set iterator.
+ +Iterator
:
+ an Iterator object containing a reference
+to all {CircuitBreaker} instances that have been created.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Iterator
object containing all
+circuits that have been created but not subsequently shut down.
+
+Returns **Iterator** an Iterator
of all available circuits
## CircuitBreaker
**Extends EventEmitter**
-Constructs a [CircuitBreaker][7].
+Constructs a [CircuitBreaker][8].
### Parameters
-- `action` **[Function][58]** The action to fire for this [CircuitBreaker][7]
-- `options` **[Object][59]** Options for the [CircuitBreaker][7]
- - `options.timeout` **[Number][60]** The time in milliseconds that action should
+- `action` **[Function][60]** The action to fire for this [CircuitBreaker][8]
+- `options` **[Object][61]** Options for the [CircuitBreaker][8]
+ - `options.timeout` **[Number][62]** The time in milliseconds that action should
be allowed to execute before timing out. Default 10000 (10 seconds)
- - `options.maxFailures` **[Number][60]** (Deprecated) The number of times the
+ - `options.maxFailures` **[Number][62]** (Deprecated) The number of times the
circuit can fail before opening. Default 10.
- - `options.resetTimeout` **[Number][60]** The time in milliseconds to wait before
+ - `options.resetTimeout` **[Number][62]** The time in milliseconds to wait before
setting the breaker to `halfOpen` state, and trying the action again.
Default: 30000 (30 seconds)
- - `options.rollingCountTimeout` **[Number][60]** Sets the duration of the
+ - `options.rollingCountTimeout` **[Number][62]** Sets the duration of the
statistical rolling window, in milliseconds. This is how long Opossum keeps
metrics for the circuit breaker to use and for publishing. Default: 10000
- - `options.rollingCountBuckets` **[Number][60]** Sets the number of buckets the
+ - `options.rollingCountBuckets` **[Number][62]** Sets the number of buckets the
rolling statistical window is divided into. So, if
options.rollingCountTimeout is 10000, and options.rollingCountBuckets is 10,
then the statistical window will be 1000 1 second snapshots in the
statistical window. Default: 10
- - `options.name` **[String][61]** the circuit name to use when reporting stats.
+ - `options.name` **[String][63]** the circuit name to use when reporting stats.
Default: the name of the function this circuit controls.
- - `options.rollingPercentilesEnabled` **[boolean][62]** This property indicates
+ - `options.rollingPercentilesEnabled` **[boolean][64]** 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. Default: false
- - `options.capacity` **[Number][60]** the number of concurrent requests allowed.
+ - `options.capacity` **[Number][62]** the number of concurrent requests allowed.
If the number currently executing function calls is equal to
options.capacity, further calls to `fire()` are rejected until at least one
of the current requests completes. Default: `Number.MAX_SAFE_INTEGER`.
- - `options.errorThresholdPercentage` **[Number][60]** the error percentage at
+ - `options.errorThresholdPercentage` **[Number][62]** the error percentage at
which to open the circuit and start short-circuiting requests to fallback.
Default: 50
- - `options.enabled` **[boolean][62]** whether this circuit is enabled upon
+ - `options.enabled` **[boolean][64]** whether this circuit is enabled upon
construction. Default: true
- - `options.allowWarmUp` **[boolean][62]** determines whether to allow failures
+ - `options.allowWarmUp` **[boolean][64]** determines whether to allow failures
without opening the circuit during a brief warmup period (this is the
`rollingCountDuration` property). Default: false
allow before enabling the circuit. This can help in situations where no
matter what your `errorThresholdPercentage` is, if the first execution
times out or fails, the circuit immediately opens. Default: 0
- - `options.volumeThreshold` **[Number][60]** the minimum number of requests within
+ - `options.volumeThreshold` **[Number][62]** the minimum number of requests within
the rolling statistical window that must exist before the circuit breaker
can open. This is similar to `options.allowWarmUp` in that no matter how many
failures there are, if the number of requests within the statistical window
does not exceed this threshold, the circuit will remain closed. Default: 0
- - `options.errorFilter` **[Function][58]** an optional function that will be
+ - `options.errorFilter` **[Function][60]** an optional function that will be
called when the circuit's function fails (returns a rejected Promise). If
this function returns truthy, the circuit's failure statistics will not be
incremented. This is useful, for example, when you don't want HTTP 404 to
@@ -224,49 +234,49 @@ Returns **void**
Determines if the circuit has been shutdown.
-Type: [Boolean][62]
+Type: [Boolean][64]
### name
Gets the name of this circuit
-Type: [String][61]
+Type: [String][63]
### group
Gets the name of this circuit group
-Type: [String][61]
+Type: [String][63]
### pendingClose
Gets whether this cicruit is in the `pendingClosed` state
-Type: [Boolean][62]
+Type: [Boolean][64]
### closed
True if the circuit is currently closed. False otherwise.
-Type: [Boolean][62]
+Type: [Boolean][64]
### opened
True if the circuit is currently opened. False otherwise.
-Type: [Boolean][62]
+Type: [Boolean][64]
### halfOpen
True if the circuit is currently half opened. False otherwise.
-Type: [Boolean][62]
+Type: [Boolean][64]
### status
-The current [Status][19] of this [CircuitBreaker][7]
+The current [Status][20] of this [CircuitBreaker][8]
-Type: [Status][64]
+Type: [Status][66]
### stats
@@ -274,13 +284,13 @@ Type: [Status][64]
Get the current stats for the circuit.
-Type: [Object][59]
+Type: [Object][61]
### hystrixStats
Get the hystrixStats.
-Type: [HystrixStats][65]
+Type: [HystrixStats][67]
### metrics
@@ -292,33 +302,33 @@ Type: PrometheusMetrics
Gets whether the circuit is enabled or not
-Type: [Boolean][62]
+Type: [Boolean][64]
### warmUp
Gets whether the circuit is currently in warm up phase
-Type: [Boolean][62]
+Type: [Boolean][64]
### volumeThreshold
Gets the volume threshold for this circuit
-Type: [Boolean][62]
+Type: [Boolean][64]
### fallback
-Provide a fallback function for this [CircuitBreaker][7]. This
+Provide a fallback function for this [CircuitBreaker][8]. This
function will be executed when the circuit is `fire`d and fails.
It will always be preceded by a `failure` event, and `breaker.fire` returns
a rejected Promise.
#### Parameters
-- `func` **([Function][58] \| [CircuitBreaker][63])** the fallback function to execute
+- `func` **([Function][60] \| [CircuitBreaker][65])** the fallback function to execute
when the breaker has opened or when a timeout or error occurs.
-Returns **[CircuitBreaker][63]** this
+Returns **[CircuitBreaker][65]** this
### fire
@@ -327,12 +337,12 @@ returned promise will be rejected. If the action succeeds, the promise will
resolve with the resolved value from action. If a fallback function was
provided, it will be invoked in the event of any failure or timeout.
-Returns **[Promise][66]<any>** promise resolves with the circuit function's return
+Returns **[Promise][68]<any>** promise resolves with the circuit function's return
value on success or is rejected on failure of the action.
### clearCache
-Clears the cache of this [CircuitBreaker][7]
+Clears the cache of this [CircuitBreaker][8]
Returns **void**
@@ -350,12 +360,12 @@ circuit breaker itself.
#### Parameters
-- `func` **[Function][58]** a health check function which returns a promise.
-- `interval` **[Number][60]?** the amount of time between calls to the health
+- `func` **[Function][60]** a health check function which returns a promise.
+- `interval` **[Number][62]?** the amount of time between calls to the health
check function. Default: 5000 (5 seconds)
-- Throws **[TypeError][67]** if `interval` is supplied but not a number
+- Throws **[TypeError][69]** if `interval` is supplied but not a number
Returns **void**
@@ -374,13 +384,22 @@ to be executed without circuit or fallback protection.
Returns **void**
+### circuits
+
+Gets a Set iterator of all active circuits. If a circuit
+has been created, but subsequently shut down, it will not
+be included in the Set iterator.
+
+Returns **Iterator** an Iterator object containing a reference
+to all {CircuitBreaker} instances that have been created.
+
## CircuitBreaker#halfOpen
Emitted after `options.resetTimeout` has elapsed, allowing for
a single attempt to call the service again. If that attempt is
successful, the circuit will be closed. Otherwise it remains open.
-Type: [Number][60]
+Type: [Number][62]
## CircuitBreaker#close
@@ -411,14 +430,14 @@ the cache, but the cache option is enabled.
Emitted when the circuit breaker is open and failing fast
-Type: [Error][68]
+Type: [Error][70]
## CircuitBreaker#timeout
Emitted when the circuit breaker action takes longer than
`options.timeout`
-Type: [Error][68]
+Type: [Error][70]
## CircuitBreaker#success
@@ -431,14 +450,14 @@ Type: any
Emitted when the rate limit has been reached and there
are no more locks to be obtained.
-Type: [Error][68]
+Type: [Error][70]
## CircuitBreaker#healthCheckFailed
Emitted with the user-supplied health check function
returns a rejected promise.
-Type: [Error][68]
+Type: [Error][70]
## CircuitBreaker#fallback
@@ -450,7 +469,7 @@ Type: any
Emitted when the circuit breaker action fails
-Type: [Error][68]
+Type: [Error][70]
## Status
@@ -458,27 +477,27 @@ Type: [Error][68]
- **See: CircuitBreaker#status**
-Tracks execution status for a given [CircuitBreaker][7].
-A Status instance is created for every [CircuitBreaker][7]
+Tracks execution status for a given [CircuitBreaker][8].
+A Status instance is created for every [CircuitBreaker][8]
and does not typically need to be created by a user.
-A Status instance will listen for all events on the [CircuitBreaker][7]
+A Status instance will listen for all events on the [CircuitBreaker][8]
and track them in a rolling statistical window. The window duration is
determined by the `rollingCountTimeout` option provided to the
-[CircuitBreaker][7]. The window consists of an array of Objects,
-each representing the counts for a [CircuitBreaker][7]'s events.
+[CircuitBreaker][8]. The window consists of an array of Objects,
+each representing the counts for a [CircuitBreaker][8]'s events.
-The array's length is determined by the [CircuitBreaker][7]'s
+The array's length is determined by the [CircuitBreaker][8]'s
`rollingCountBuckets` option. The duration of each slice of the window
is determined by dividing the `rollingCountTimeout` by
`rollingCountBuckets`.
### Parameters
-- `options` **[Object][59]** for the status window
- - `options.rollingCountBuckets` **[Number][60]** number of buckets in the window
- - `options.rollingCountTimeout` **[Number][60]** the duration of the window
- - `options.rollingPercentilesEnabled` **[Boolean][62]** whether to calculate
+- `options` **[Object][61]** for the status window
+ - `options.rollingCountBuckets` **[Number][62]** number of buckets in the window
+ - `options.rollingCountTimeout` **[Number][62]** the duration of the window
+ - `options.rollingPercentilesEnabled` **[Boolean][64]** whether to calculate
percentiles
### Examples
@@ -500,37 +519,37 @@ circuit.status.window;
Get the cumulative stats for the current window
-Type: [Object][59]
+Type: [Object][61]
### window
Gets the stats window as an array of time-sliced objects.
-Type: [Array][69]
+Type: [Array][71]
## Status#snapshot
Emitted at each time-slice. Listeners for this
event will receive a cumulative snapshot of the current status window.
-Type: [Object][59]
+Type: [Object][61]
## HystrixStats
- **See: CircuitBreaker#hystrixStats**
-Stream Hystrix Metrics for a given [CircuitBreaker][7].
-A HystrixStats instance is created for every [CircuitBreaker][7]
+Stream Hystrix Metrics for a given [CircuitBreaker][8].
+A HystrixStats instance is created for every [CircuitBreaker][8]
and does not typically need to be created by a user.
A HystrixStats instance will listen for all events on the
-[Status#snapshot][70]
+[Status#snapshot][72]
and format the data to the proper Hystrix format.
Making it easy to construct an Event Stream for a client
### Parameters
-- `the` **[CircuitBreaker][63]** circuit breaker
+- `the` **[CircuitBreaker][65]** circuit breaker
### Examples
@@ -566,130 +585,134 @@ Returns **void**
[6]: #factorymetrics
-[7]: #circuitbreaker
+[7]: #factorycircuits
+
+[8]: #circuitbreaker
+
+[9]: #parameters-2
-[8]: #parameters-2
+[10]: #close
-[9]: #close
+[11]: #open
-[10]: #open
+[12]: #shutdown
-[11]: #shutdown
+[13]: #isshutdown
-[12]: #isshutdown
+[14]: #name
-[13]: #name
+[15]: #group
-[14]: #group
+[16]: #pendingclose
-[15]: #pendingclose
+[17]: #closed
-[16]: #closed
+[18]: #opened
-[17]: #opened
+[19]: #halfopen
-[18]: #halfopen
+[20]: #status
-[19]: #status
+[21]: #stats
-[20]: #stats
+[22]: #hystrixstats
-[21]: #hystrixstats
+[23]: #metrics
-[22]: #metrics
+[24]: #enabled
-[23]: #enabled
+[25]: #warmup
-[24]: #warmup
+[26]: #volumethreshold
-[25]: #volumethreshold
+[27]: #fallback
-[26]: #fallback
+[28]: #parameters-3
-[27]: #parameters-3
+[29]: #fire
-[28]: #fire
+[30]: #clearcache
-[29]: #clearcache
+[31]: #healthcheck
-[30]: #healthcheck
+[32]: #parameters-4
-[31]: #parameters-4
+[33]: #enable
-[32]: #enable
+[34]: #disable
-[33]: #disable
+[35]: #circuits
-[34]: #circuitbreakerhalfopen
+[36]: #circuitbreakerhalfopen
-[35]: #circuitbreakerclose
+[37]: #circuitbreakerclose
-[36]: #circuitbreakeropen
+[38]: #circuitbreakeropen
-[37]: #circuitbreakerfire
+[39]: #circuitbreakerfire
-[38]: #circuitbreakercachehit
+[40]: #circuitbreakercachehit
-[39]: #circuitbreakercachemiss
+[41]: #circuitbreakercachemiss
-[40]: #circuitbreakerreject
+[42]: #circuitbreakerreject
-[41]: #circuitbreakertimeout
+[43]: #circuitbreakertimeout
-[42]: #circuitbreakersuccess
+[44]: #circuitbreakersuccess
-[43]: #circuitbreakersemaphorelocked
+[45]: #circuitbreakersemaphorelocked
-[44]: #circuitbreakerhealthcheckfailed
+[46]: #circuitbreakerhealthcheckfailed
-[45]: #circuitbreakerfallback
+[47]: #circuitbreakerfallback
-[46]: #circuitbreakerfailure
+[48]: #circuitbreakerfailure
-[47]: #status-1
+[49]: #status-1
-[48]: #parameters-5
+[50]: #parameters-5
-[49]: #examples-1
+[51]: #examples-1
-[50]: #stats-1
+[52]: #stats-1
-[51]: #window
+[53]: #window
-[52]: #statussnapshot
+[54]: #statussnapshot
-[53]: #hystrixstats-1
+[55]: #hystrixstats-1
-[54]: #parameters-6
+[56]: #parameters-6
-[55]: #examples-2
+[57]: #examples-2
-[56]: #gethystrixstream
+[58]: #gethystrixstream
-[57]: #shutdown-1
+[59]: #shutdown-1
-[58]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
+[60]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
-[59]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
+[61]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
-[60]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
+[62]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
-[61]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
+[63]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
-[62]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
+[64]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
-[63]: #circuitbreaker
+[65]: #circuitbreaker
-[64]: #status
+[66]: #status
-[65]: #hystrixstats
+[67]: #hystrixstats
-[66]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
+[68]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
-[67]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError
+[69]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError
-[68]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
+[70]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error
-[69]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
+[71]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
-[70]: Status#snapshot
+[72]: Status#snapshot
diff --git a/index.js b/index.js
index 187f1cfb..9db45fde 100644
--- a/index.js
+++ b/index.js
@@ -1,7 +1,7 @@
'use strict';
const CircuitBreaker = require('./lib/circuit');
-const circuits = [];
+let lastCircuit;
const defaults = {
timeout: 10000, // 10 seconds
@@ -64,10 +64,9 @@ const defaults = {
* @return {CircuitBreaker} a newly created {@link CircuitBreaker} instance
*/
function factory (action, options) {
- const circuit = new CircuitBreaker(action,
+ lastCircuit = new CircuitBreaker(action,
Object.assign({}, defaults, options));
- circuits.push(circuit);
- return circuit;
+ return lastCircuit;
}
/**
@@ -88,14 +87,13 @@ factory.promisify = require('./lib/promisify');
/**
* Get the Prometheus metrics for all circuits.
* @function factory.metrics
- * @return {String} the metrics for all circuits
+ * @return {String} the metrics for all circuits or
+ * undefined if no circuits have been created
*/
factory.metrics = function metrics() {
// Just get the metrics for the last circuit that was created
// since prom-client is additive
- const lastCircuit = circuits[circuits.length - 1];
- if (lastCircuit && lastCircuit.metrics)
- return lastCircuit.metrics.metrics;
+ if (lastCircuit && lastCircuit.metrics) return lastCircuit.metrics.metrics;
}
let warningIssued = false;
@@ -110,6 +108,14 @@ Object.defineProperty(factory, 'stats', {
}
});
+/**
+ * Get an Iterator
object containing all
+ * circuits that have been created but not subsequently shut down.
+ * @function factory.circuits
+ * @return {Iterator} an Iterator
of all available circuits
+ */
+factory.circuits = CircuitBreaker.circuits;
+
module.exports = exports = factory;
// Allow use of default import syntax in TypeScript
module.exports.default = factory;
diff --git a/lib/circuit.js b/lib/circuit.js
index d7c4cbf6..0b84e5e5 100644
--- a/lib/circuit.js
+++ b/lib/circuit.js
@@ -27,6 +27,7 @@ const WARMING_UP = Symbol('warming-up');
const VOLUME_THRESHOLD = Symbol('volume-threshold');
const deprecation = `options.maxFailures is deprecated. \
Please use options.errorThresholdPercentage`;
+const CIRCUITS = new Set();
let warningIssued = false;
@@ -191,6 +192,7 @@ class CircuitBreaker extends EventEmitter {
options.prometheusRegistry
);
}
+ CIRCUITS.add(this);
}
/**
@@ -242,6 +244,7 @@ class CircuitBreaker extends EventEmitter {
this.hystrixStats.shutdown();
this.metrics && this.metrics.clear();
this[STATE] = SHUTDOWN;
+ CIRCUITS.delete(this);
}
/**
@@ -663,4 +666,15 @@ const nextName = () =>
return v.toString(16);
});
+/**
+ * Gets a Set iterator of all active circuits. If a circuit
+ * has been created, but subsequently shut down, it will not
+ * be included in the Set iterator.
+ *
+ * @returns {Iterator} an Iterator object containing a reference
+ * to all {CircuitBreaker} instances that have been created.
+ */
+CircuitBreaker.circuits = function circuits() {
+ return CIRCUITS.values();
+}
module.exports = exports = CircuitBreaker;
diff --git a/test/browser/index.js b/test/browser/index.js
index f87acbb8..75281557 100644
--- a/test/browser/index.js
+++ b/test/browser/index.js
@@ -6,7 +6,6 @@ require('../enable-disable-test.js');
require('../error-filter-test.js');
require('../half-open-test.js');
require('../health-check-test.js');
-require('../hystrix-order-test.js');
require('../hystrix-test.js');
require('../semaphore-test.js');
require('../test.js');
diff --git a/test/circuit-shutdown-test.js b/test/circuit-shutdown-test.js
index 85b6bf63..23f57bb5 100644
--- a/test/circuit-shutdown-test.js
+++ b/test/circuit-shutdown-test.js
@@ -31,3 +31,26 @@ test('Circuit shuts down properly', t => {
t.end();
});
});
+
+test('A list of non-shutdown circuits is maintained', t => {
+ function expectCount(iterator, count) {
+ // eslint-disable-next-line no-empty-pattern
+ for (let {} of iterator) count--;
+ return count === 0;
+ }
+
+ t.ok(expectCount(circuit.circuits(), 0));
+
+ const c1 = circuit(passFail);
+ const c2 = circuit(passFail);
+
+ t.ok(expectCount(circuit.circuits(), 2));
+
+ c2.shutdown();
+ t.ok(expectCount(circuit.circuits(), 1));
+
+ c1.shutdown();
+ t.ok(expectCount(circuit.circuits(), 0));
+
+ t.end();
+});