{"id":15194939,"url":"https://github.com/auth0/disyuntor","last_synced_at":"2025-04-10T01:08:26.738Z","repository":{"id":54573441,"uuid":"71823711","full_name":"auth0/disyuntor","owner":"auth0","description":"A circuit-breaker implementation for node.js","archived":false,"fork":false,"pushed_at":"2024-10-25T18:31:24.000Z","size":273,"stargazers_count":49,"open_issues_count":1,"forks_count":13,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-04-03T00:04:33.053Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/auth0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2016-10-24T19:18:41.000Z","updated_at":"2025-03-31T10:32:35.000Z","dependencies_parsed_at":"2024-06-18T21:29:38.751Z","dependency_job_id":"9abca6a6-8b8a-4418-a7fe-6584aced0350","html_url":"https://github.com/auth0/disyuntor","commit_stats":{"total_commits":98,"total_committers":13,"mean_commits":7.538461538461538,"dds":"0.24489795918367352","last_synced_commit":"a67eecb82c20f0c9a5e5ed1e7004cf6d61738060"},"previous_names":["jfromaniello/disyuntor"],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/auth0%2Fdisyuntor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/auth0%2Fdisyuntor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/auth0%2Fdisyuntor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/auth0%2Fdisyuntor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/auth0","download_url":"https://codeload.github.com/auth0/disyuntor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248137895,"owners_count":21053775,"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":[],"created_at":"2024-09-27T23:03:44.800Z","updated_at":"2025-04-10T01:08:26.721Z","avatar_url":"https://github.com/auth0.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/auth0/disyuntor.svg?branch=master)](https://travis-ci.org/auth0/disyuntor)\n\nA [circuit-breaker](http://martinfowler.com/bliki/CircuitBreaker.html) implementation for node.js with exponential backoff.\n\n**Disyuntor** is the Spanish word used for circuit-breaker.\n\nThe purpose of this pattern is to detect errors and prevent cascading failures across multiple systems.\n\nDisyuntor wraps an async (errback) function and returns a new function with the same signature.\n\nDuring normal behavior of the system the circuit remains in its `closed` state. This means that every call to the wrapper is forwarded to the protected function.\n\nOnce the protected function returns more than `maxFailures`, the breaker trips and every call made during the `cooldown` interval will immediately return an error preventing resource depletion. This is known as the `open` state.\n\nOnce the system has settled it will allow one call to go to the protected function. If the call succeeds the breaker will be reset to its `closed` state otherwise it will continue `open`. This state is known as `half open`\n\nA call is considered to have failed if the callback is not called before the `timeout` or if it is called with the first (error) parameter.\n\n## Installation\n\n```\nnpm i disyuntor\n```\n\n## Basic usage\n\n```javascript\nconst disyuntor = require('disyuntor');\n\nconst dnsSafeLookup = disyuntor.wrapCallbackApi({\n  //This is used in error messages.\n  name: 'dns.lookup',\n\n  //Timeout for the protected function.\n  // timeout: '2s',\n\n  //The number of consecutive failures before switching to open mode\n  //and stop calling the underlying service.\n  // maxFailures: 5,\n\n  //The minimum time the circuit remains open before doing another attempt.\n  // cooldown: '15s',\n\n  //The maximum amount of time the circuit remains open before doing a new attempt.\n  // maxCooldown: '60s',\n\n  //optionally log errors\n  onTrip: (err, failures, cooldown) =\u003e {\n    console.log(`dns.lookup triped because it failed ${failures} times.\nLast error was ${err.message}! There will be no more attempts for ${cooldown}ms.`);\n  },\n\n  onClose: (cooldown) =\u003e {\n    console.log(`dns.lookup circuit closed after ${cooldown}ms.`;\n  }\n\n  // //optional callback to prevent some errors to trigger the disyuntor logic\n  // //in this case ENOTFOUND is passed to the callback and will\n  // //not trigger the breaker eg:\n  // trigger: (err) =\u003e err.code !== 'ENOTFOUND'\n}, dns.lookup);\n\n//then use as you will normally use dns.lookup\ndnsSafeLookup('google.com', (err, ip) =\u003e {\n  if (err) { return console.error(err.message); }\n  console.log(ip);\n})\n```\n\nTimeouts can be expressed either by strings like '15s' or by milliseconds.\n\nDefaults values are:\n\n- `timeout`: 2s\n- `maxFailures`: 5\n- `cooldown`: 15s\n- `maxCooldown`: 60s\n\n\n## Protecting Promise APIs\n\n```javascript\nconst lookup = Promise.promisify(require('dns').lookup);\n\nconst protectedLookup = disyuntor.wrapPromise({\n  name: 'dns.lookup',\n  timeout: '2s',\n  maxFailures: 2\n}, lookup);\n\nprotectedLookup('google.com')\n  .then((ip)  =\u003e console.log(ip),\n        (err) =\u003e console.error(err));\n```\n\n## Complex scenarios\n\nYou can create an instance of Disyuntor to have more control as follows:\n\n```javascript\nconst Disyuntor = require('disyuntor').Disyuntor;\n\nconst disyuntor = new Disyuntor({\n  name: 'dns.lookup',\n  timeout: '2s',\n  maxFailures: 2\n});\n\nawait disyuntor.protect(() =\u003e dns.lookupAsync('google.com'));\n```\n\nNote: this api only supports promise-returning functions.\n## License\n\nCopyright (c) 2015 Auth0, Inc. \u003csupport@auth0.com\u003e (http://auth0.com)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fauth0%2Fdisyuntor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fauth0%2Fdisyuntor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fauth0%2Fdisyuntor/lists"}