{"_id":"@carbonteq/resilience","_rev":"2-142afdcddbe12be9dafad751bb82cee5","name":"@carbonteq/resilience","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@carbonteq/resilience","version":"0.0.1","keywords":["circuit-breaker","retry","backoff","jitter","resilience","timeout","fallback","fluent","polly"],"author":{"name":"Carbonteq"},"license":"MIT","_id":"@carbonteq/resilience@0.0.1","maintainers":[{"name":"volf","email":"rslnkrmt2552@gmail.com"},{"name":"irfanatcarbonteq","email":"irfan@carbonteq.com"},{"name":"adm-carbonteq","email":"admin@carbonteq.com"}],"homepage":"https://github.com/carbonteq/resilience#readme","bugs":{"url":"https://github.com/carbonteq/resilience/issues"},"nyc":{"all":true,"exclude":["**/*.test.{ts,js}"],"include":["dist/**/*.js","src/**/*.ts"],"reporter":["cobertura","text-summary","html"],"extension":[".ts"],"instrument":true},"dist":{"shasum":"7c0e1d74d067da6b211ffc3094d7091ea882d55b","tarball":"https://registry.npmjs.org/@carbonteq/resilience/-/resilience-0.0.1.tgz","fileCount":284,"integrity":"sha512-O2YzNKt+cHErlu3oMgS3eTeKnLlAGz2PlDmoKfSAE/OnFqC6Q6iAHobFbv4xJbvnpzKbVkpaV2qIOlBCbdRAlg==","signatures":[{"sig":"MEUCIQCW4xCIAeZNdrh91U4BgCo2HoNrrJOtT+93mYjpjUQoGwIgX2GgwiDPDnbrxL2rM3lDeQIm0U1TDDDUHar+ZLsudT8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":758711,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj6jg8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo8mhAAhSPyg1vTvWewzwpEH/RNLSs12cmF/1yWdTquwtwJZD+V/j3V\r\nSGXE7vLQUEqb/EOBsHwgiRF7a4s5Qn5Sk7CRxa8bthsTPWNCWBpyxAS52W7L\r\n6/8zEKdayM0i2Qr0ktv0g+rMnOPDlA4USCdkrjXdU1YPY4ZtpEdUZM2Gg5RH\r\n752ExTfMAbIl/zfc4Hs8mOH+J/u8W380Iiz0eI4zGijEKU97YRiJjbPtIzVb\r\nV4WvNuM/O5xfmoz1FyfpakrAV54aVGAtfy7q5CepHz9x9NTHMIwuQKQy51NP\r\nf/rkpz4Fn5YAOOT+DRKZC5nK6E5M3f5rh4R4TyVbTwtwv/rSeDUmvQtq+YMF\r\nmk1eKHZoK9NLEZNA9wokcWtnpDDIQPuxyhvaisWFFkDc9du/S7O4h/k/JmMP\r\nmH+cP/3lnrSaq6lHOLzMM+bugkG/0diTGhy/A5ugIkhlBDxz11JQkPZx9B8N\r\nQ1z3VLvUR5aF95bier4ETR0Q0p8GAIbWIOsaVIeTmdWdLAM6R88wjn2fpiT0\r\n0W86TpSEFHlIpz8JrH/iTQaXl5FiAgngPOPfOhMYdWZCPJWyRCjJeDZ2Ya3R\r\nwGbjQFSL+hXw730V8DDy5mb7GoFsHa0jLizqrn6y21/fPkXvmjp9SCt9i7mb\r\n5SCamnAHAbLchvs2QlxjHr43ODfeYeDFlgI=\r\n=QMX0\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","types":"./dist/index.d.ts","module":"dist/esm/index.js","engines":{"node":">=16"},"gitHead":"c412d64458c5c9fb068685ecfa5f81bc1b1ddc5f","scripts":{"fmt":"remark readme.md -f -o readme.md && prettier --write \"src/**/*.ts\" \"*.md\"","test":"rimraf dist && tsc && npm run test:unit && npm run test:fmt && npm run test:md","watch":"rimraf dist && tsc --watch","compile":"rimraf dist && tsc && tsc -p tsconfig.esm.json","test:md":"remark -f readme.md -q","test:fmt":"prettier --list-different \"src/**/*.ts\" \"*.md\"","test:unit":"mocha","test:cover":"rimraf dist && tsc && nyc npm run test:unit","pre:compile":"npm run compile"},"_npmUser":{"name":"irfanatcarbonteq","email":"irfan@carbonteq.com"},"prettier":{"printWidth":100,"arrowParens":"avoid","singleQuote":true,"trailingComma":"all"},"repository":{"url":"git+ssh://git@github.com/carbonteq/resilience.git","type":"git"},"_npmVersion":"8.5.5","description":"A resilience and transient-fault-handling library that allows developers to express policies such as Backoff, Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. Inspired by .NET Polly.","directories":{},"sideEffects":false,"_nodeVersion":"16.15.0","dependencies":{"moment":"^2.29.4","ioredis":"^5.3.1"},"_hasShrinkwrap":false,"devDependencies":{"nyc":"^15.1.0","chai":"^4.3.6","mocha":"^10.0.0","sinon":"^14.0.0","rimraf":"^3.0.2","prettier":"^2.6.2","remark-cli":"^10.0.1","remark-toc":"^8.0.1","sinon-chai":"^3.7.0","typescript":"^4.7.4","@types/chai":"^4.3.1","@types/node":"^16.11.7","chai-subset":"^1.6.0","@types/mocha":"^9.1.1","@types/sinon":"^10.0.11","ioredis-mock":"^8.2.6","chai-as-promised":"^7.1.1","@types/sinon-chai":"^3.2.8","@types/chai-subset":"^1.3.3","source-map-support":"^0.5.21","remark-validate-links":"^11.0.2","@types/chai-as-promised":"^7.1.5"},"_npmOperationalInternal":{"tmp":"tmp/resilience_0.0.1_1676294204622_0.9618386377092418","host":"s3://npm-registry-packages"}}},"time":{"created":"2023-02-13T13:16:44.514Z","modified":"2025-03-24T07:32:04.891Z","0.0.1":"2023-02-13T13:16:44.833Z"},"bugs":{"url":"https://github.com/carbonteq/resilience/issues"},"author":{"name":"Carbonteq"},"license":"MIT","homepage":"https://github.com/carbonteq/resilience#readme","keywords":["circuit-breaker","retry","backoff","jitter","resilience","timeout","fallback","fluent","polly"],"repository":{"url":"git+ssh://git@github.com/carbonteq/resilience.git","type":"git"},"description":"A resilience and transient-fault-handling library that allows developers to express policies such as Backoff, Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. Inspired by .NET Polly.","maintainers":[{"email":"rslnkrmt2552@gmail.com","name":"volf"},{"email":"admin@carbonteq.com","name":"adm-carbonteq"},{"email":"irfan@carbonteq.com","name":"irfanatcarbonteq"},{"email":"owais.ahsan@carbonteq.com","name":"owaisatcarbonteq"}],"readme":"<div align=\"center\">\n<h3 align=\"center\">Resilience</h3>\n\n  <p align=\"center\">\n    Resilience is built on [Cockatiel](https://github.com/connor4312/cockatiel) with redis.\n  </p>\n</div>\n\n<details>\n  <summary>Table of Contents</summary>\n  <ol>\n    <li>\n      <a href=\"#about-the-project\">About The Project</a>\n      <ul>\n        <li><a href=\"#built-with\">Built With</a></li>\n      </ul>\n    </li>\n    <li>\n      <a href=\"#getting-started\">Getting Started</a>\n      <ul>\n        <li><a href=\"#prerequisites\">Prerequisites</a></li>\n        <li><a href=\"#installation\">Installation</a></li>\n      </ul>\n    </li>\n    <li><a href=\"#usage\">Usage</a></li>\n    <li><a href=\"#contributing\">Contributing</a></li>\n  </ol>\n</details>\n\n## About The Project\n\nAn enhancement to a circuit breaker with a rate limiter to protect your application from overloading due to excessive requests. The breaker can be used to stop sending requests to a service that is failing or is overloaded together with the rate limiter that limits the number of requests that can be made within a certain time period. Together, circuit breaker and rate limiter can help prevent your application from crashing or becoming unresponsive due to too many requests.\n\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n### Built With\n\nThis project is built on the top of cockatiel.\n\n* [Cockatiel](https://github.com/connor4312/cockatiel)\n\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n<!-- GETTING STARTED -->\n\n## Getting Started\n\nYou should have a basic setup of nodejs project using typescript\n\n### Prerequisites\n\nShould have a sound knowledge of Circuit Breaker, Rate Limiter and typescript. Redis should be installed on your machine\n\n### Installation\n\n1. Install redis sampling breaker package\n   ```sh\n   npm i @carbonteq/resilience\n   ```\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n## Usage\n\nThen go forth with sampling breaker:\n\n```js\nimport {\n  ExponentialBackoff,\n  retry,\n  handleAll,\n  circuitBreaker,\n  wrap,\n  RedisSamplingBreaker\n} from '@carbonteq/resilience';\nimport axios from \"axios\";\nimport Redis from \"ioredis\";\n\n// Create a retry policy that'll try whatever function we execute 3\n// times with a randomized exponential backoff.\nconst retry = retry(handleAll, { maxAttempts: 3, backoff: new ExponentialBackoff() });\n\n// Create a circuit breaker that'll stop calling the executed function for 10\n// seconds if it fails 5 times in a row. This can give time for e.g. a database\n// to recover without getting tons of traffic.\nconst circuitBreakerPolicy = circuitBreaker(handleAll, {\n  halfOpenAfter: 10 * 1000,\n  breaker: new RedisSamplingBreaker({ threshold: 0.2, duration: 30 * 1000, redisClient: new Redis() }),\n});\n\n// Combine these! Create a policy that retries 3 times, calling through the circuit breaker\nconst retryWithBreaker = wrap(retry, circuitBreakerPolicy);\n\nexports.handleRequest = async (req, res) => {\n  const data = await retryWithBreaker.execute(() => axios.get(\"http://127.0.0.1:8080\"));\n  return res.json(data);\n};\n```\n\n\nWith rate limiting policy and sliding window counter driver:\n\n```js\nimport * as crypto from \"crypto\"\nimport axios from \"axios\";\nimport Redis from \"ioredis\";\nimport {handleAll, rateLimiter,SlidingWindowCounterDriver } from \"@carbonteq/resilience\";\n\nexports.handleRequest = async (req, res) => {\n  const hash = crypto.createHash(\"md5\").update(req.ip).digest(\"hex\");\n  const rateLimiterPolicy = rateLimiter(handleAll, {\n    redisClient: new Redis(),\n    driver: new SlidingWindowCounterDriver({\n      hash: hash,\n      maxWindowRequestCount: 5,\n      intervalInSeconds: 1 * 60,\n    }),\n  });\n\n  const data = await rateLimiterPolicy.execute(() => axios.get(\"http://127.0.0.1:8080\"));\n  return res.json(data);\n};\n```\n\nWith rate limiting policy and leaky bucket driver:\n\n```js\nimport * as crypto from \"crypto\"\nimport axios from \"axios\";\nimport Redis from \"ioredis\";\nimport { handleAll, rateLimiter,LeakyBucketDriver } from \"@carbonteq/resilience\";\n\nexports.handleRequest = async (req, res) => {\n  const hash = crypto.createHash(\"md5\").update(req.ip).digest(\"hex\");\n  const rateLimiterPolicy = rateLimiter(handleAll, {\n    redisClient: new Redis(),\n    driver: new LeakyBucketDriver({\n      hash: hash,\n      bucketSize: 5,\n      fillRate: 10,\n    }),\n  });\n\n  const data = await rateLimiterPolicy.execute(() => axios.get(\"http://127.0.0.1:8080\"));\n  return res.json(data);\n};\n```\n\nWrap both rate limiting and sampling breaker:\n\n```js\nimport * as crypto from \"crypto\"\nimport {\n  handleAll,\n  retry,\n  circuitBreaker,\n  rateLimiter,\n  RedisSamplingBreaker,\n  SlidingWindowCounterDriver\n} from '@carbonteq/resilience';\nimport axios from \"axios\";\nimport Redis from \"ioredis\";\n\nconst circuitBreakerPolicy = circuitBreaker(handleAll, {\n  halfOpenAfter: 10 * 1000,\n  breaker: new SamplingBreaker({ threshold: 0.2, duration: 30 * 1000,redisClient: new Redis() }),\n});\n\nconst retryPolicy = retry(handleAll, {\n  maxAttempts: 3,\n  backoff: new ExponentialBackoff(),\n});\nexports.handleRequest = async (req, res) => {\n    const hash = crypto.createHash(\"md5\").update(req.ip).digest(\"hex\");\n    const rateLimiterPolicy = rateLimiter(handleAll, {\n      redisClient: new Redis(),\n      driver: new SlidingWindowCounterDriver({\n        hash: hash,\n        maxWindowRequestCount: 5,\n        intervalInSeconds: 1 * 60,\n      }),\n    });\n\n  \n  const retryWithBreaker = wrap(redisRateLimiterPolicy,retryPolicy,circuitBreakerPolicy);\n  const data = await retryWithBreaker.execute(() => axios.get(\"http://127.0.0.1:8080\"));\n  return res.json(data);\n};\n```\n\n\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any\ncontributions you make are **greatly appreciated**.\n\nIf you have a suggestion that would make this better, please fork the repo and create a pull request. You can also\nsimply open an issue with the tag \"enhancement\". Don't forget to give the project a star! Thanks again!\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>","readmeFilename":"readme.md"}