npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@syrf/circuit-breaker

v1.0.2

Published

Circuit breaker for promised based service

Downloads

7

Readme

circuit-breaker

Circuit breaker library for NodeJs to handle and monitor unstable or slow operation like http request to external service. circuit-breaker breaks internal circuit when average failure has reached a threshold value and provide fallback service while backing off the service so it can recover


States

There are three states of circuit breakers

  • closed : Normal state of the circuit
  • open : State when failure threshold reached, call to the handled service will immediately return CircuitBroken error or execute fallback service
  • half open : State after interval passed and circuit will try to execute service again. if success threshold reached circuit will close. if failure threshold reached again, circuit will open again

Examples

Basic Usage

const Breaker = require('circuit-breaker');

const unstableService = (parameter1, parameter2) => {
  return new Promise((resolve, reject) => {
    //call to an unstable service
    console.log(parameter1, parameter2);
    //will print hello world
  });
};

const breaker = Breaker.create(unstableService)
  .withFailureThreshold(0.3)
  .withSuccessThreshold(0.5);

const parameter1 = 'Hello';
const parameter2 = 'World';
breaker.exec(parameter1, parameter2);

Fallback

const unstableService = (parameter1, parameter2) => {
  return new Promise((resolve, reject) => {
    //call to an unstable service
    reject(new Error('Some Error'));
  });
};

const fallbackService = (parameter1, parameter2) => {
  return new Promise((resolve, reject) => {
    console.log('Fallback ', parameter1, parameter2);
    //will print Fallback hello world
  });
};

const breaker =
  Breaker.create(unstableService).withFallbackService(fallbackService);

const parameter1 = 'Hello';
const parameter2 = 'World';
breaker.exec(parameter1, parameter2);

Intervals

Interval define time span after circuit broke to switch to half open for retries

Fixed Interval

const breaker = Breaker.create(unstableService).withBackoffInterval({
  interval: 10 * 1000,
});

Incremental Interval

const breaker = Breaker.create(unstableService).withBackoffInterval({
  increment: 5 * 1000, //will increase interval by 5s every retry
});

Exponential Interval

Exponential interval will power the interval by the number of retry

const breaker = Breaker.create(unstableService).withBackoffInterval({
  exponentInterval: true,
});

For more real case examples you can check the examples directory

Constructor

circuit breaker accepts two arguments

  • service : function which returns Promise
  • config : configuration object

Configurations

Available configuration options : Config | Type | Default | Description ---|---|---|--- name|string|defaultBrake|name of service. mostly used to identify service on global monitor group |string|defaultGroup|name of service group. mostly used to identify service on global monitor failureThreshold |number|0.5|average failure threshold to trigger circuit to break successThreshold |number|0.5|average success threshold to trigger circuit to recover interval|number|10000|Time interval in milliseconds to back off the service increment|number|0|Time interval increment in milliseconds. incremented when circuit is closed again after half open state exponentInterval|boolean|false|Flag to set interval to exponential if the service keeps on failing. the interval value in second will be powered to number of attempt to connect timeout|number|3000|Max execution time in milliseconds for handled service fallback|method|null|Fallback method expected to return promise bucketSpan|number|1000|time span of a bucket to should remain active bucketCount|number|60|number of buckets to retain in a rolling window statsInterval|number|5000|time interval between stats reporting registerGlobal|boolean|true|specify if circuit breaker should be regitered in global stats

Builder Methods Samples

List of builder methods to ease up configuring circuit breaker

  • static Breaker.create(service)
  • .withFallbackService(serviceFallback)
  • .withFailureThreshold(0.35)
  • .withSuccessThreshold(0.65)
  • .withBackoffInterval({ interval: 1000, increment : 2000, exponential : false })
  • .withBucket({ bucketSpan: 5000, bucketCount : 10 })
  • .withExecutionTimeout(3000)
  • .withStatsInterval(1000)

withBackoffInterval and withBucket accept object as parameter. every field of the object is optional, if value not provided, default value will be used

Methods

| Method | Argument(s) | Returns | Description | | ----------------------- | ------------------------------------------ | ----------- | ----------------------------------------------------------- | | static getGlobalStats | N/A | globalStats | Returns global status where all circuit breakers registered | | exec | Same arguments with the registered service | Promise | Returns the same promise as the registered service | | on | string,function | N/A | Standard EventEmitter listening |

Non Breaking Error

When handling service using library like axios, we often get expected error like 400 errors etc. but those kind of error is not considered as breaking errors because the error thrown does not indicate that the service is not working properly. to be able to handle the error just like normal error without opening the circuit NonBreakingError can be thrown.

const restService = () => {
  return new Promise((resolve, reject) => {
    axios
      .get('http://example.com/api')
      .then(resolve)
      .catch((err) => {
        // check if the response is started with 400 (400,401,404 etc)
        if (err?.response?.status?.toString()?.[0] === '4') {
          // throw non breaking error
          reject(new Breaker.NonBreakingError(err?.response));
        } else {
          // this will add failure count and opens circuit eventually
          reject(err);
        }
      });
  });
};

Events

List of events emitted by circuit breaker :

  • exec : Event on service execution start
  • failure : Event on service execution failed
  • success : Event on service execution success
  • timeout : Event on service execution timeout
  • circuitClosed : Event when circuit closed
  • circuitOpen : Event when circuit open
  • circuitHalfOpen : Event when circuit half open
  • stats : Event when circuit sends stats

Stats

Circuit breaker will emit stats event with latest stats data based on statsInterval interval Stats object sample :

{
    name: 'defaultBrake',
    group: 'defaultGroup',
    state: 'CLOSED',
    failureThreshold: 0.5,
    successThreshold: 0.5,
    nextAttempt: 1619424986009,
    retryCount: 0,
    bucketSpan: 1000,
    bucketCount: 60,
    increment: 0,
    exponentInterval: false,
    interval: 10000,
    timeout: 3000,
    stats: {
        avgSuccess: 0.9,
        avgFailure: 0.5,
        failed : 10,
        successful : 90,
        total : 100,
        shortCircuited : 0,
        timedOut : 5,
        avgLatency : 1023
    },

}

Global Stats

Global stats will listen to the stats Event emitted by all registered circuit breaker and push the stats to a readable stream

const globalStats = Breaker.getGlobalStats();
globalStats.stream.on('data', (data) => {
  //handle data
  console.log(data);
});

Development

To develop locally clone the repo and use the following commands :

npm install
npm run test