GithubHelp home page GithubHelp logo

levee's Introduction

Levee

A circuit breaker implementation based heavily on ryanfitz's node-circuitbreaker. More information about the circuitbreaker pattern can be found in the akka documentation.

Build Status Greenkeeper badge

Basic Usage

'use strict';

var Levee = require('levee');
var Wreck = require('@hapi/wreck');

var options, circuit;

options = {
    maxFailures: 5,
    timeout: 60000,
    resetTimeout: 30000
};

circuit = Levee.createBreaker(callbackifyWreck, options);
circuit.run('http://www.google.com', function (err, req, payload) {
    // If the service fails or timeouts occur 5 consecutive times,
    // the breaker opens, fast failing subsequent requests.
    console.log(err || payload);
});

//Levee command must have a callback based interface
function callbackifyWreck(url, cb) {
    Wreck.get(url)
    .then(({ res, payload }) => cb(null, res, payload))
    .catch(err => cb(err, null, null))

Advanced Usage

function fallback(url, callback) {
    callback(null, null, new Buffer('The requested website is not available. Please try again later.'));
}

circuit = Levee.createBreaker(service, options);
circuit.fallback = Levee.createBreaker(fallback, options);

circuit.on('timeout', function () {
    console.log('Request timed out.');
});

circuit.on('failure', function (err) {
    console.log('Request failed.', err);
});

circuit.run('http://www.google.com', function (err, req, payload) {
    // If the service fails or timeouts occur 5 consecutive times,
    // the breaker opens, fast failing subsequent requests.
    console.log(err || payload);
});

var stats, fbStats;
stats = Levee.createStats(circuit);
fbStats = Levee.createStats(circuit.fallback);

// Print stats every 5 seconds.
setInterval(function () {
    console.log(stats.snapshot());
    console.log(fbStats.snapshot());
}, 5000);

API

new Breaker(command [, options])

Creates a new Breaker instance with the following arguments:

  • command - an object with a property named execute with value being a function using the signature: function (context, callback) where:
    • context - Any context needed to execute the desired behavior.
    • callback - A callback function with the signature function (err, [arg1, arg2, ...])
var Levee = require('levee');

var breaker = new Levee.Breaker({ execute: fn }, options);

createBreaker(command [, options])

An alternative method for creating Breaker instances with the following arguments:

  • command - either function or an object with a property named execute with value being a function using the signature: function (context, callback) where:
    • context - Any context needed to execute the desired behavior.
    • callback - A callback function with the signature function (err, [arg1, arg2, ...])
var Levee = require('levee');

function doStuff(context, callback) {
    callback(null, 'ok');
}

var breaker = Levee.createBreaker(fn, options);

new Stats(breaker)

Create a new Stats instance with the following argument:

  • breaker - a Breaker instance
var Levee = require('levee');

var breaker = new Levee.Stats(breaker);

createStats(breaker)

An alternative method for creating a new Stats instance with the following argument:

  • breaker - a Breaker instance
var Levee = require('levee');

var breaker = Levee.createStats(breaker);

Breaker

new Levee.Breaker(command, options) or Levee.createBreaker(command, options)

Options

timeout

the amount of time to allow an operation to run before terminating with an error.

maxFailures

the number of failures allowed before the Breaker enters the open state.

resetTimeout

the amount of time to wait before switch the Breaker from the open to half_open state to attempt recovery.

isFailure

function that returns true if an error should be considered a failure (receives the error object returned by your command.) This allows for non-critical errors to be ignored by the circuit breaker.

timeoutErrMsg

Custom error message to be used, for timeout error.

openErrMsg

Custom error message to be used, when circuit is open and command is not available.

Properties

fallback

a Breaker instance to fallback to in the case of the Breaker entering the open state.

Methods

run(context, callback)

Executes the wrapped functionality within the circuit breaker functionality with the arguments:

  • context - any context to be provided to the implementation.
  • callback - the callback to be fired upon completion with the signature function (err, [param1, param2, ...])

Stats

new Levee.Stats(breaker, options) or Levee.createStats(breaker, options)

A simple data aggregation object.

Options

maxSamples

Restricts the length of duration samples. The default value is 1000.

Methods

increment(name)

Increment a named counter.

  • name - the label of the counter to increment.
decrement(name)

Decrement a named counter.

  • name - the label of the counter to decrement.
sample(name, value)

Take a sample of a given value.

  • name - the label of the sample being recorded.
  • value - the sample value being recorded.
snapshot()

Get the current state of the current Stats instance. Returns an object with the following properties:

  • counts - A map of names to current count values.
  • samples - A map of names to current sample averages and counts, in the form of: { average: 0, count, 0 }
reset()

Resets all counts and samples.

resetCounts([name])

Reset counts for the provided name. If no name is provided, resets all counts.

  • name - the label of the count to reset.
resetSamples([name])

Reset samples for the provided name. If no name is provided, resets all samples.

  • name - the label of the sample to reset.

levee's People

Contributors

grawk avatar greenkeeper[bot] avatar maxmil7 avatar shaunwarman avatar shirhuang avatar snowinferno avatar subeeshcbabu avatar sumeetkakkar avatar tlivings avatar totherik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

levee's Issues

Question about `circuit.run`

I want to be able to run circuitBreaker with extra options for the context.
For example:

I want to be able to do

circuit = levee.createBreaker(wreck.get, circuitOptions);
circuit.run(uri, {header: <someHeaderInfo>, timeout: timeOutValue}, function (err, req, payload) {
  .......
  .......
});

This does not seem possible today as run only takes the context and callback as arguments. Am i missing something ? I went down the path of understanding if I can stash uri and the extra options information into context itself, but i quickly realized the execute function that actually invokes the operation in the breaker forces arguments to just be the context and callback.

If this is indeed a bug, I would like to take a stab at fixing it.

Basic example doesn't work

When trying the Levee Basic Example, the following error gets thrown.

Williams-MacBook-Pro:levee-basic-example blaine$ node index.js
/Users/blaine/Documents/node_modules/wreck/lib/index.js:474
    return this._shortcutWrap('GET', uri, options, callback);
                ^

TypeError: this._shortcutWrap is not a function
    at Object.internals.Client.get [as execute] (/Users/blaine/Documents/node_modules/wreck/lib/index.js:474:17)
    at zalgo (/Users/blaine/Documents/node_modules/levee/lib/zalgo.js:28:12)
    at Breaker._run (/Users/blaine/Documents/node_modules/levee/lib/breaker.js:125:13)
    at Breaker.run (/Users/blaine/Documents/node_modules/levee/lib/breaker.js:60:15)
    at Object.<anonymous> (/Users/blaine/Documents/levee-basic-example/index.js:21:9)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)

I made a quick repo to demonstrate: https://github.com/wbprice/levee-basic-example

blaine$ node -v
v6.9.1

Update: Seems to be an issue with Wreck. I was playing with examples/http.js and it worked using the version of Wreck that comes with Levee, but failed when updating Wreck to the latest version.

Support for EventEmitters

Some modules communicate errors via EventEmitter error events. This current API doesn't support any way to allow those errors to contribute to breaker management. Add API to allow this behavior.

Levee is a synchronous library

Hi folks. I wanted to give some feedback after using it for a week and suggest an improvement to the documentation. I discovered fairly late into my exploration that execution through a circuit instance is synchronous. Adding this piece to the documentation might be very helpful for high-level understanding of Levee for newcomers. Thanks!

Can I do POST requests?

Does levee support request types other than GET? It would be nice to be able to do POST, PUT, DELETE and other types of request.

Support Promises

I want to use Levee around my axios instance but if I have understood correctly, Levee only works with functions that supports callbacks and not promises. So is there any plan to do provide such functionality? otherwise i can raise a PR for it.

Multiple requests

Hi there,

Love this module!

Just wandering if I am making multiple requests to different endpoints, do I need a circuit per endpoint url?

Thanks
Louis

Support for streams

Hi when doing a request with for example the request module, sometimes you want to do the request as streams and pipe the response. Meaning that there is no callback, instead you have to watch for the stream returned by request.get being destroyed (maybe with an error).

It would be awesome if levee supported streaming.

Basically breaker.run will return a stream and you have to attach to .on('close', ...) and .on('error', ...), etc. for breaking/timeout etc.

The module end-of-stream would be handy for this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.