{"id":13464762,"url":"https://github.com/nodeshift/opossum","last_synced_at":"2025-04-23T20:49:23.512Z","repository":{"id":37820164,"uuid":"72322823","full_name":"nodeshift/opossum","owner":"nodeshift","description":"Node.js circuit breaker - fails fast  ⚡️ ","archived":false,"fork":false,"pushed_at":"2025-03-18T07:59:40.000Z","size":9568,"stargazers_count":1415,"open_issues_count":20,"forks_count":109,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-04-22T18:51:01.120Z","etag":null,"topics":["breaker","circuit","circuit-breaker","fail-fast","fallback","hystrix","hystrix-dashboard","promise"],"latest_commit_sha":null,"homepage":"https://nodeshift.dev/opossum/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nodeshift.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-10-30T03:29:49.000Z","updated_at":"2025-04-22T15:12:27.000Z","dependencies_parsed_at":"2023-10-03T15:04:45.502Z","dependency_job_id":"a8ee034c-e87a-4892-8d66-66de33ac194b","html_url":"https://github.com/nodeshift/opossum","commit_stats":{"total_commits":756,"total_committers":53,"mean_commits":"14.264150943396226","dds":0.6666666666666667,"last_synced_commit":"7d004cb63aebb9718ed1510c28d9eea6a0aba9ad"},"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeshift%2Fopossum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeshift%2Fopossum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeshift%2Fopossum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeshift%2Fopossum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nodeshift","download_url":"https://codeload.github.com/nodeshift/opossum/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250513799,"owners_count":21443204,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["breaker","circuit","circuit-breaker","fail-fast","fallback","hystrix","hystrix-dashboard","promise"],"created_at":"2024-07-31T14:00:49.950Z","updated_at":"2025-04-23T20:49:23.495Z","avatar_url":"https://github.com/nodeshift.png","language":"JavaScript","readme":"# opossum\n\n![Node.js CI](https://github.com/nodeshift/opossum/workflows/Node.js%20CI/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/nodeshift/opossum/badge.svg?branch=master)](https://coveralls.io/github/nodeshift/opossum?branch=master)\n[![Known Vulnerabilities](https://snyk.io/test/npm/opossum/badge.svg)](https://snyk.io/test/npm/opossum)\n[![Dependency Status](https://img.shields.io/librariesio/github/nodeshift/opossum)](https://libraries.io/nodeshift/opossum)\n\nOpossum is a Node.js circuit breaker that executes asynchronous functions\nand monitors their execution status. When things start failing, `opossum`\nplays dead and fails fast. If you want, you can provide a fallback function\nto be executed when in the failure state.\n\nFor more about the circuit breaker pattern, there are lots of resources\non the web - search it! Fowler's blog post is one place to\n[start reading](http://martinfowler.com/bliki/CircuitBreaker.html).\n\n|                 | Project Info  |\n| --------------- | ------------- |\n| License:        | Apache-2.0  |\n| Documentation:  | https://nodeshift.dev/opossum/ |\n| Typings:        | https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/opossum\n| Issue tracker:  | https://github.com/nodeshift/opossum/issues  |\n| Engines:        | Node.js \u003e= 16 |\n\n## Usage\n\nLet's say you've got an API that depends on something that might fail -\na network operation, or disk read, for example. Wrap those functions up in a\n`CircuitBreaker` and you have control over your destiny.\n\n```javascript\nconst CircuitBreaker = require('opossum');\n\nfunction asyncFunctionThatCouldFail(x, y) {\n  return new Promise((resolve, reject) =\u003e {\n    // Do something, maybe on the network or a disk\n  });\n}\n\nconst options = {\n  timeout: 3000, // If our function takes longer than 3 seconds, trigger a failure\n  errorThresholdPercentage: 50, // When 50% of requests fail, trip the circuit\n  resetTimeout: 30000 // After 30 seconds, try again.\n};\nconst breaker = new CircuitBreaker(asyncFunctionThatCouldFail, options);\n\nbreaker.fire(x, y)\n  .then(console.log)\n  .catch(console.error);\n```\n\n### AbortController support\n\nYou can provide an `AbortController` (https://developer.mozilla.org/en-US/docs/Web/API/AbortController, https://nodejs.org/docs/latest/api/globals.html#globals_class_abortcontroller) for aborting on going request upon\nreaching Opossum timeout.\n\n```javascript\nconst CircuitBreaker = require('opossum');\nconst http = require('http');\n\nfunction asyncFunctionThatCouldFail(abortSignal, x, y) {\n  return new Promise((resolve, reject) =\u003e {\n    http.get(\n      'http://httpbin.org/delay/10',\n      { signal: abortSignal },\n      (res) =\u003e {\n        if(res.statusCode \u003c 300) {\n          resolve(res.statusCode);\n          return;\n        }\n\n        reject(res.statusCode);\n      }\n    );\n  });\n}\n\nconst abortController = new AbortController();\nconst options = {\n  abortController,\n  timeout: 3000, // If our function takes longer than 3 seconds, trigger a failure\n};\nconst breaker = new CircuitBreaker(asyncFunctionThatCouldFail, options);\n\nbreaker.fire(abortController.signal)\n  .then(console.log)\n  .catch(console.error);\n```\n\n### Auto Renew AbortController\n\nThe `autoRenewAbortController` option allows the automatic renewal of the `AbortController` when the circuit breaker transitions into the `halfOpen` or `closed` states. This feature ensures that the `AbortController` can be reused properly for ongoing requests without manual intervention.\n\n```javascript\nconst CircuitBreaker = require('opossum');\nconst http = require('http');\n\nfunction asyncFunctionThatCouldFail(abortSignal, x, y) {\n  return new Promise((resolve, reject) =\u003e {\n    http.get(\n      'http://httpbin.org/delay/10',\n      { signal: abortSignal },\n      (res) =\u003e {\n        if(res.statusCode \u003c 300) {\n          resolve(res.statusCode);\n          return;\n        }\n\n        reject(res.statusCode);\n      }\n    );\n  });\n}\n\nconst abortController = new AbortController();\nconst options = {\n  autoRenewAbortController: true,\n  timeout: 3000, // If our function takes longer than 3 seconds, trigger a failure\n};\nconst breaker = new CircuitBreaker(asyncFunctionThatCouldFail, options);\n\nconst signal = breaker.getSignal();\nbreaker.fire(signal)\n  .then(console.log)\n  .catch(console.error);\n```\n\n### Fallback\n\nYou can also provide a fallback function that will be executed in the\nevent of failure. To take some action when the fallback is performed,\nlisten for the `fallback` event.\n\n```javascript\nconst breaker = new CircuitBreaker(asyncFunctionThatCouldFail, options);\n// if asyncFunctionThatCouldFail starts to fail, firing the breaker\n// will trigger our fallback function\nbreaker.fallback(() =\u003e 'Sorry, out of service right now');\nbreaker.on('fallback', (result) =\u003e reportFallbackEvent(result));\n```\n\nOnce the circuit has opened, a timeout is set based on `options.resetTimeout`.\nWhen the `resetTimeout` expires, `opossum` will enter the `halfOpen` state.\nOnce in the `halfOpen` state, the next time the circuit is fired, the circuit's\naction will be executed again. If successful, the circuit will close and emit\nthe `close` event. If the action fails or times out, it immediately re-enters\nthe `open` state.\n\nWhen a fallback function is triggered, it's considered a failure, and the\nfallback function will continue to be executed until the breaker is closed.\n\nThe fallback function accepts the same parameters as the fire function:\n\n```javascript\nconst delay = (delay, a, b, c) =\u003e\n  new Promise((resolve) =\u003e {\n    setTimeout(() =\u003e {\n      resolve();\n    }, delay);\n  });\n\nconst breaker = new CircuitBreaker(delay);\nbreaker.fire(20000, 1, 2, 3);\nbreaker.fallback((delay, a, b, c) =\u003e `Sorry, out of service right now. But your parameters are: ${delay}, ${a}, ${b} and ${c}`);\n```\n### Breaker State Initialization\n\nThere may be times where you will need to initialize the state of a Circuit Breaker.  Primary use cases for this are in a serverless environment such as Knative or AWS Lambda, or any container based platform, where the container being deployed is ephemeral.\n\nThe `toJSON` method is a helper function to get the current state and status of a breaker:\n\n```\nconst breakerState = breaker.toJSON();\n```\n\nThis will return an object that might look similar to this:\n\n```\n{\n  state: {\n    enabled: true,\n    name: 'functionName'\n    closed: true,\n    open: false,\n    halfOpen: false,\n    warmUp: false,\n    shutdown: false\n  },\n  status: {\n    ...\n  }\n};\n```\n\nA new circuit breaker instance can be created with this state by passing this object in:\n\n```\nconst breaker = new CircuitBreaker({state: state});\n```\n\n### Status Initialization\n\nThere may also be times where you will need to pre-populate the stats of the Circuit Breaker Status Object.  Primary use cases for this are also in a serverless environment such as Knative or AWS Lambda, or any container based platform, where the container being deployed is ephemeral.\n\nGetting the existing cumulative stats for a breaker can be done like this:\n\n```\nconst stats = breaker.stats;\n```\n\n`stats` will be an object that might look similar to this:\n\n```\n{\n  failures: 11,\n  fallbacks: 0,\n  successes: 5,\n  rejects: 0,\n  fires: 16,\n  timeouts: 0,\n  cacheHits: 0,\n  cacheMisses: 0,\n  coalesceCacheHits: 0,\n  coalesceCacheMisses: 0,\n  semaphoreRejections: 0,\n  percentiles: {\n    '0': 0,\n    '1': 0,\n    '0.25': 0,\n    '0.5': 0,\n    '0.75': 0,\n    '0.9': 0,\n    '0.95': 0,\n    '0.99': 0,\n    '0.995': 0\n  },\n  latencyTimes: [ 0 ],\n  latencyMean: 0\n}\n```\n\nTo then re-import those stats, first create a new `Status` object with the previous stats and then pass that as an option to the CircuitBreaker constructor:\n\n```\nconst statusOptions = {\n  stats: {....}\n};\n\nconst newStatus = CircuitBreaker.newStatus(statusOptions);\n\nconst breaker = new CircuitBreaker({status: newStatus});\n```\n\n### Browser\n\nOpossum really shines in a browser. You can use it to guard against network\nfailures in your AJAX calls.\n\nWe recommend using [webpack](https://webpack.js.org/) to bundle your applications,\nsince it does not have the effect of polluting the `window` object with a global.\nHowever, if you need it, you can access a `circuitBreaker` function in the global\nnamespace by doing something similar to what is shown in the below example.\n\nHere is an example using [hapi.js](https://hapijs.com). See the\n[opossum-examples](https://github.com/nodeshift-starters/opossum-examples/)\nrepository for more detail.\n\nInclude `opossum.js` in your HTML file.\n\n```html\n\u003chtml\u003e\n\u003chead\u003e\n  \u003ctitle\u003eMy Super App\u003c/title\u003e\n  \u003cscript type='text/javascript' src=\"/jquery.js\"\u003e\u003c/script\u003e\n  \u003cscript type='text/javascript' src=\"/opossum.js\"\u003e\u003c/script\u003e\n  \u003cscript type='text/javascript' src=\"/app.js\"\u003e\u003c/script\u003e\n\u003cbody\u003e\n...\n\u003c/body\u003e\n\u003c/head\u003e\n\u003c/html\u003e\n```\n\nIn your application, set a route to the file, pointing to\n`node_modules/opossum/dist/opossum-min.js`.\n\n```js\n// server.js\nconst server = new Hapi.Server();\nserver.register(require('inert', (err) =\u003e possibleError(err)));\nserver.route({\n  method: 'GET',\n  path: '/opossum.js',\n  handler: {\n    file: {\n      path: path.join(__dirname, 'node_modules', 'opossum', 'dist', 'opossum-min.js'),\n    }\n  }\n});\n```\nIn the browser's global scope will be a `CircuitBreaker` constructor. Use it\nto create circuit breakers, guarding against network failures in your REST\nAPI calls.\n\n```js\n// app.js\nconst route = 'https://example-service.com/rest/route';\nconst circuitBreakerOptions = {\n  timeout: 500,\n  errorThresholdPercentage: 50,\n  resetTimeout: 5000\n};\n\nconst breaker = new CircuitBreaker(() =\u003e $.get(route), circuitBreakerOptions);\nbreaker.fallback(() =\u003e `${route} unavailable right now. Try later.`));\nbreaker.on('success', (result) =\u003e $(element).append(JSON.stringify(result)}));\n\n$(() =\u003e {\n  $('#serviceButton').click(() =\u003e breaker.fire().catch((e) =\u003e console.error(e)));\n});\n\n```\n\n### Events\n\nA `CircuitBreaker` will emit events for important things that occur.\nHere are the events you can listen for.\n\n  * `fire` - emitted when the breaker is fired.\n  * `reject` - emitted when the breaker is open (or halfOpen).\n  * `timeout` - emitted when the breaker action times out.\n  * `success` - emitted when the breaker action completes successfully\n  * `failure` - emitted when the breaker action fails, called with the error\n  * `open` - emitted when the breaker state changes to `open`\n  * `close` - emitted when the breaker state changes to `closed`\n  * `halfOpen` - emitted when the breaker state changes to `halfOpen`\n  * `fallback` - emitted when the breaker has a fallback function and executes it\n  * `semaphoreLocked` - emitted when the breaker is at capacity and cannot execute the request\n  * `healthCheckFailed` - emitted when a user-supplied health check function returns a rejected promise\n  * `shutdown` - emitted when the breaker shuts down\n\nHandling events gives a greater level of control over your application behavior.\n\n```js\nconst breaker = new CircuitBreaker(() =\u003e $.get(route), circuitBreakerOptions);\n\nbreaker.fallback(() =\u003e ({ body: `${route} unavailable right now. Try later.` }));\n\nbreaker.on('success',\n  (result) =\u003e $(element).append(\n    makeNode(`SUCCESS: ${JSON.stringify(result)}`)));\n\nbreaker.on('timeout',\n  () =\u003e $(element).append(\n    makeNode(`TIMEOUT: ${route} is taking too long to respond.`)));\n\nbreaker.on('reject',\n  () =\u003e $(element).append(\n    makeNode(`REJECTED: The breaker for ${route} is open. Failing fast.`)));\n\nbreaker.on('open',\n  () =\u003e $(element).append(\n    makeNode(`OPEN: The breaker for ${route} just opened.`)));\n\nbreaker.on('halfOpen',\n  () =\u003e $(element).append(\n    makeNode(`HALF_OPEN: The breaker for ${route} is half open.`)));\n\nbreaker.on('close',\n  () =\u003e $(element).append(\n    makeNode(`CLOSE: The breaker for ${route} has closed. Service OK.`)));\n\nbreaker.on('fallback',\n  (data) =\u003e $(element).append(\n    makeNode(`FALLBACK: ${JSON.stringify(data)}`)));\n```\n\n\n### Promises vs. Callbacks\nThe `opossum` API returns a `Promise` from `CircuitBreaker.fire()`.\nBut your circuit action - the async function that might fail -\ndoesn't have to return a promise. You can easily turn Node.js style\ncallback functions into something `opossum` understands by using the built in\nNode core utility function `util.promisify()` .\n\n```javascript\nconst fs = require('fs');\nconst { promisify } = require('util');\nconst CircuitBreaker = require('opossum');\n\nconst readFile = promisify(fs.readFile);\nconst breaker = new CircuitBreaker(readFile, options);\n\nbreaker.fire('./package.json', 'utf-8')\n  .then(console.log)\n  .catch(console.error);\n```\n\nAnd just for fun, your circuit doesn't even really have to be a function.\nNot sure when you'd use this - but you could if you wanted to.\n\n```javascript\nconst breaker = new CircuitBreaker('foo', options);\n\nbreaker.fire()\n  .then(console.log) // logs 'foo'\n  .catch(console.error);\n```\n\n### Calculating errorThresholdPercentage\n\nThe `errorThresholdPercentage` value is compared to the error rate. That rate is determined by dividing the number of failures by the number of times the circuit has been fired. You can see this comparison here:\n\n```js\n// check stats to see if the circuit should be opened\n  const stats = circuit.stats;\n  if ((stats.fires \u003c circuit.volumeThreshold) \u0026\u0026 !circuit.halfOpen) return;\n  const errorRate = stats.failures / stats.fires * 100;\n  if (errorRate \u003e circuit.options.errorThresholdPercentage || circuit.halfOpen) {\n    circuit.open();\n  }\n```\n\nThe numbers for `fires` and `failures` come from the stats that are indeed governed by `rollingCountTimeout` and `rollingCountBuckets`. The timeout value is the total number of seconds for which the stats are being maintained, and the buckets value is the number of slots in the window. The defaults are 10 seconds and 10 buckets. So, the statistics that are being compared against `errorThresholdPercentage` are based on 10 samples, one per second over the last 10 seconds.\n\nExample: a circuit is fired 24 times over 10 seconds with a somewhat bursty pattern, failing three times.\n\n```\n| fires: 2 | fires: 1 | fires: 3 | fires: 0 | fires: 9 | fires: 3 | fires: 2 | fires: 0 | fires: 4 | fires: 0 |\n| fails: 0 | fails: 0 | fails: 0 | fails: 0 | fails: 0 | fails: 3 | fails: 0 | fails: 0 | fails: 0 | fails: 0 |\n```\nThe failure rate here is 3/24 or 1/8 or 12.5%. The default error threshold is 50%, so in this case, the circuit would not open. However, if you modified the `rollingCountTimeout` to 3 seconds, and the `rollingCountBuckets` to 3  (not recommended), then the stats array might look like these three seconds from above.\n\n```\n| fires: 3 | fires: 2 | fires: 0 |\n| fails: 3 | fails: 0 | fails: 0 |\n```\nNow, without changing `errorThresholdPercentage` our circuit will open because our error rate is now 3/5 or 60%. It's tricky to test this stuff because the array of statistics is a rolling count. Every second the oldest bucket is removed and a new one is added, so the totals change constantly in a way that may not be intuitive.\n\nFor example, if the first example is shifted right, dropping the first bucket and adding another with `fires: 3` the total number of `fires` now in the stats is not 27 (24+3) but 25 (24-2+3).\n\nThe code that is summing the stats samples is here:\n\n```js\n  const totals = this[WINDOW].reduce((acc, val) =\u003e {\n    if (!val) { return acc; }\n    Object.keys(acc).forEach(key =\u003e {\n      if (key !== 'latencyTimes' \u0026\u0026 key !== 'percentiles') {\n        (acc[key] += val[key] || 0);\n      }\n    });\n\n    if (this.rollingPercentilesEnabled) {\n      acc.latencyTimes.push.apply(acc.latencyTimes, val.latencyTimes || []);\n    }\n    return acc;\n  }, bucket());\n```\n\n### Coalesce calls\n\nCircuitbreaker offers coalescing your calls. If options.coalesce is set, multiple calls to the circuitbreaker will be handled as one, within the given timeframe (options.coalesceTTL). Performance will improve when rapidly firing the circuitbreaker with the same request, especially on a slower action. This is especially useful if multiple events can trigger the same functions at the same time. Of course, caching has the same function, but will only be effective when the call has been successfully executed once to store the return value. Coalescing and cache can be used at the same time, coalescing calls will always use the internal cache. Accessing cache is done prior to coalescing. When using `capacity` option, coalescing reduces the capacity used for the CircuitBreaker and will allow higher throughput of the rest of the application without actually firing the CircuitBreaker protected function. The `cacheGetKey` option is used for coalescing as well.\n\n#### Finetuning Coalesce behavior\n\nBy default, all calls within given timeframe are coalesced, including errors and timeouts. This might be unwanted, as this twarths retry mechanisms etc. To finetune coalesce behavior, use the coalesceResetOn parameter. Some examples:\n\n| coalesceResetOn value | behavior |\n| --------------------- | -------- |\n| `error`, `success`, `timeout` | coalescing is reset after every 'done' status, so only concurrent 'running' calls are coalesced. One could consider this the most essential form of coalescing. |\n| `error`, `timeout` | No error state is being stored for longer than the running call, you might want to start here if you use any retry mechanisms. |\n| `error` | Reset on errors. |\n| `timeout` | Reset on timeouts. |\n| `success` | Reset on success. |\n\nYou can use any combination of `error`, `success`, `timeout`.\n\n#### Using CircuitBreaker with Coalescing and fetch.\n\nWhen using the CircuitBreaker with Coalescing enabled to protect calling external services using the Fetch API, it's important to keep this in mind: The Response interface of the Fetch API does not allow reading the same body multiple times, cloning the Response will not help either as it will delay the reading of the response until the slowest reader is done. To work around this you can either choose to wrap handling of the response (e.g. parsing) in the protected function as well, keep in mind any errors and delays in this process will amount to the error thresholds configured. This might not be suitable for complexer setups. Another option would be to flatten the response and revive it. This might come in handy when working with libraries that expect a Response object. Example below:\n\n```js\nconst flattenResponse = async (r) =\u003e ({\n  arrayBuffer: await r.arrayBuffer(),\n  init: {\n    headers: r.headers,\n    ok: r.ok,\n    redirected: r.redirected,\n    status: r.status,\n    statusText: r.statusText,\n    type: r.type,\n    url: r.url,\n  },\n});\n\nconst reviveResponse = (r) =\u003e new Response(r.arrayBuffer, r.init);\n```\n\nAlso note, Fetch doesn't fail on HTTP errors (e.g. 50x). If you want to protect your application from calling failing APIs, check the response status and throw errors accordingly.\n\n\n### Typings\n\nTypings are available [here](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/opossum).\n\nIf you'd like to add them, run `npm install @types/opossum` in your project.\n\n### Metrics\n\n#### Prometheus\nThe [`opossum-prometheus`](https://github.com/nodeshift/opossum-prometheus) module\ncan be used to produce metrics that are consumable by Prometheus.\nThese metrics include information about the circuit itself, for example how many\ntimes it has opened, as well as general Node.js statistics, for example event loop lag.\n\n\n#### Hystrix\nThe [`opossum-hystrix`](https://github.com/nodeshift/opossum-hystrix) module can\nbe used to produce metrics that are consumable by the Hystrix Dashboard.\n\n## Troubleshooting\n\nYou may run into issues related to too many listeners on an `EventEmitter` like this.\n\n```sh\n(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 10 unpipe listeners added. Use emitter.setMaxListeners() to increase limit\n(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 drain listeners added. Use emitter.setMaxListeners() to increase limit\n(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit\n(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 close listeners added. Use emitter.setMaxListeners() to increase limit\n(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 finish listeners added. Use emitter.setMaxListeners() to increase limit\n```\n\nIn some cases, seeing this error might indicate a bug in client code, where many `CircuitBreaker`s are inadvertently being created. But there are legitimate scenarios where this may not be the case. For example, it could just be that you need more than 10 `CircuitBreaker`s in your app. That's ok.\n\nTo get around the error, you can set the number of listeners on the stream.\n\n```js\nbreaker.stats.getHystrixStream().setMaxListeners(100);\n```\n\nOr it could be that you have a large test suite which exercises some code that creates `CircuitBreaker`s and does so repeatedly. If the `CircuitBreaker` being created is only needed for the duration of the test, use `breaker.shutdown()` when the circuit is no longer in use to clean up all listeners.\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnodeshift%2Fopossum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnodeshift%2Fopossum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnodeshift%2Fopossum/lists"}