All Projects → nodeshift → Opossum

nodeshift / Opossum

Licence: apache-2.0
Node.js circuit breaker - fails fast ⚡️

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Opossum

Heimdall
An enhanced HTTP client for Go
Stars: ✭ 2,132 (+350.74%)
Mutual labels:  circuit-breaker, hystrix
spring-microservices
Spring Cloud Micro Services with Eureka Discovery, Zuul Proxy, OAuth2 Security, Hystrix CircuitBreaker, Sleuth Zipkin, ELK Stack Logging, Kafka, Docker and many new features
Stars: ✭ 114 (-75.9%)
Mutual labels:  hystrix, circuit-breaker
Sample Camel Spring Boot
three samples in different branches that illustrates usage of apache camel as microservice framework providing integration with consul, hystrix, ribbon and other tools
Stars: ✭ 24 (-94.93%)
Mutual labels:  circuit-breaker, hystrix
Connectors
Connectors simplify connecting to standalone and CloudFoundry services
Stars: ✭ 28 (-94.08%)
Mutual labels:  hystrix, circuit-breaker
clj-http-hystrix
A Clojure library to wrap clj-http requests as hystrix commands
Stars: ✭ 21 (-95.56%)
Mutual labels:  hystrix, circuit-breaker
Hystrix.Dotnet
A combination of circuit breaker and timeout. The .net version of the open source Hystrix library built by Netflix.
Stars: ✭ 88 (-81.4%)
Mutual labels:  hystrix, circuit-breaker
yato
A node module similar to hystrix. Who caused riots - cut it!
Stars: ✭ 12 (-97.46%)
Mutual labels:  hystrix, circuit-breaker
microservices-developer-roadmap
Roadmap for becoming a Microservice Developer in 2017
Stars: ✭ 24 (-94.93%)
Mutual labels:  hystrix, circuit-breaker
gobreak
Latency and fault tolerance library like Netflix's Hystrix with prometheus and gobreaker.
Stars: ✭ 42 (-91.12%)
Mutual labels:  hystrix, circuit-breaker
pyhystrix
Hystrix brought to Python
Stars: ✭ 21 (-95.56%)
Mutual labels:  hystrix, circuit-breaker
Brakes
Hystrix compliant Node.js Circuit Breaker Library
Stars: ✭ 255 (-46.09%)
Mutual labels:  circuit-breaker, hystrix
Await Timeout
A Promise-based API for setTimeout / clearTimeout
Stars: ✭ 404 (-14.59%)
Mutual labels:  promise
Replace In File
A simple utility to quickly replace contents in one or more files
Stars: ✭ 369 (-21.99%)
Mutual labels:  promise
Sample Spring Microservices
Many samples in different branches that shows how to create microservices with Spring Boot, Spring Cloud, Zipkin, Zuul, Eureka, Hystrix, Kubernetes, Elastic Stack and many more tools
Stars: ✭ 368 (-22.2%)
Mutual labels:  hystrix
Fun Task
Abstraction for managing asynchronous code in JS
Stars: ✭ 363 (-23.26%)
Mutual labels:  promise
Basic Ftp
FTP client for Node.js, supports FTPS over TLS, passive mode over IPv6, async/await, and Typescript.
Stars: ✭ 441 (-6.77%)
Mutual labels:  promise
Octokat.js
Github API Client using Promises or callbacks. Intended for the browser or NodeJS.
Stars: ✭ 401 (-15.22%)
Mutual labels:  promise
Lamp Cloud
lamp-cloud 基于Jdk11 + SpringCloud + SpringBoot的微服务快速开发平台,其中的可配置的SaaS功能尤其闪耀, 具备RBAC功能、网关统一鉴权、Xss防跨站攻击、自动代码生成、多种存储系统、分布式事务、分布式定时任务等多个模块,支持多业务系统并行开发, 支持多服务并行开发,可以作为后端服务的开发脚手架。代码简洁,注释齐全,架构清晰,非常适合学习和企业作为基础框架使用。
Stars: ✭ 4,125 (+772.09%)
Mutual labels:  hystrix
Angular Admin
🔏Admin client for surmon.me blog powered by @angular and Bootstrap4
Stars: ✭ 352 (-25.58%)
Mutual labels:  promise
Ws
⚠️ Deprecated - (in favour of Networking) ☁️ Elegantly connect to a JSON api. (Alamofire + Promises + JSON Parsing)
Stars: ✭ 352 (-25.58%)
Mutual labels:  promise

opossum

Node.js CI Coverage Status Known Vulnerabilities dependencies Status

Opossum is a Node.js circuit breaker that executes asynchronous functions and monitors their execution status. When things start failing, opossum plays dead and fails fast. If you want, you can provide a fallback function to be executed when in the failure state.

For more about the circuit breaker pattern, there are lots of resources on the web - search it! Fowler's blog post is one place to start reading.

Project Info
License: Apache-2.0
Documentation: https://nodeshift.dev/opossum/
Typings: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/opossum
Issue tracker: https://github.com/nodeshift/opossum/issues
Engines: Node.js >= 10

Usage

Let's say you've got an API that depends on something that might fail - a network operation, or disk read, for example. Wrap those functions up in a CircuitBreaker and you have control over your destiny.

const CircuitBreaker = require('opossum');

function asyncFunctionThatCouldFail(x, y) {
  return new Promise((resolve, reject) => {
    // Do something, maybe on the network or a disk
  });
}

const options = {
  timeout: 3000, // If our function takes longer than 3 seconds, trigger a failure
  errorThresholdPercentage: 50, // When 50% of requests fail, trip the circuit
  resetTimeout: 30000 // After 30 seconds, try again.
};
const breaker = new CircuitBreaker(asyncFunctionThatCouldFail, options);

breaker.fire(x, y)
  .then(console.log)
  .catch(console.error);

Fallback

You can also provide a fallback function that will be executed in the event of failure. To take some action when the fallback is performed, listen for the fallback event.

const breaker = new CircuitBreaker(asyncFunctionThatCouldFail, options);
// if asyncFunctionThatCouldFail starts to fail, firing the breaker
// will trigger our fallback function
breaker.fallback(() => 'Sorry, out of service right now');
breaker.on('fallback', (result) => reportFallbackEvent(result));

Once the circuit has opened, a timeout is set based on options.resetTimeout. When the resetTimeout expires, opossum will enter the halfOpen state. Once in the halfOpen state, the next time the circuit is fired, the circuit's action will be executed again. If successful, the circuit will close and emit the close event. If the action fails or times out, it immediately re-enters the open state.

When a fallback function is triggered, it's considered a failure, and the fallback function will continue to be executed until the breaker is closed.

The fallback function accepts the same parameters as the fire function:

const delay = (delay, a, b, c) =>
  new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, delay);
  });

const breaker = new CircuitBreaker(delay);
breaker.fire(20000, 1, 2, 3);
breaker.fallback((delay, a, b, c) => `Sorry, out of service right now. But your parameters are: ${delay}, ${a}, ${b} and ${c}`);

Browser

Opossum really shines in a browser. You can use it to guard against network failures in your AJAX calls.

We recommend using webpack to bundle your applications, since it does not have the effect of polluting the window object with a global. However, if you need it, you can access a circuitBreaker function in the global namespace by doing something similar to what is shown in the below example.

Here is an example using hapi.js. See the opossum-examples repository for more detail.

Include opossum.js in your HTML file.

<html>
<head>
  <title>My Super App</title>
  <script type='text/javascript' src="/jquery.js"></script>
  <script type='text/javascript' src="/opossum.js"></script>
  <script type='text/javascript' src="/app.js"></script>
<body>
...
</body>
</head>
</html>

In your application, set a route to the file, pointing to node_modules/opossum/dist/opossum-min.js.

// server.js
const server = new Hapi.Server();
server.register(require('inert', (err) => possibleError(err)));
server.route({
  method: 'GET',
  path: '/opossum.js',
  handler: {
    file: {
      path: path.join(__dirname, 'node_modules', 'opossum', 'dist', 'opossum-min.js'),
    }
  }
});

In the browser's global scope will be a CircuitBreaker constructor. Use it to create circuit breakers, guarding against network failures in your REST API calls.

// app.js
const route = 'https://example-service.com/rest/route';
const circuitBreakerOptions = {
  timeout: 500,
  errorThresholdPercentage: 50,
  resetTimeout: 5000
};

const breaker = new CircuitBreaker(() => $.get(route), circuitBreakerOptions);
breaker.fallback(() => `${route} unavailable right now. Try later.`));
breaker.on('success', (result) => $(element).append(JSON.stringify(result)}));

$(() => {
  $('#serviceButton').click(() => breaker.fire().catch((e) => console.error(e)));
});

Events

A CircuitBreaker will emit events for important things that occur. Here are the events you can listen for.

  • fire - emitted when the breaker is fired.
  • reject - emitted when the breaker is open (or halfOpen).
  • timeout - emitted when the breaker action times out.
  • success - emitted when the breaker action completes successfully
  • failure - emitted when the breaker action fails, called with the error
  • open - emitted when the breaker state changes to open
  • close - emitted when the breaker state changes to closed
  • halfOpen - emitted when the breaker state changes to halfOpen
  • fallback - emitted when the breaker has a fallback function and executes it
  • semaphoreLocked - emitted when the breaker is at capacity and cannot execute the request
  • healthCheckFailed - emitted when a user-supplied health check function returns a rejected promise

Handling events gives a greater level of control over your application behavior.

const breaker = new CircuitBreaker(() => $.get(route), circuitBreakerOptions);

breaker.fallback(() => ({ body: `${route} unavailable right now. Try later.` }));

breaker.on('success',
  (result) => $(element).append(
    makeNode(`SUCCESS: ${JSON.stringify(result)}`)));

breaker.on('timeout',
  () => $(element).append(
    makeNode(`TIMEOUT: ${route} is taking too long to respond.`)));

breaker.on('reject',
  () => $(element).append(
    makeNode(`REJECTED: The breaker for ${route} is open. Failing fast.`)));

breaker.on('open',
  () => $(element).append(
    makeNode(`OPEN: The breaker for ${route} just opened.`)));

breaker.on('halfOpen',
  () => $(element).append(
    makeNode(`HALF_OPEN: The breaker for ${route} is half open.`)));

breaker.on('close',
  () => $(element).append(
    makeNode(`CLOSE: The breaker for ${route} has closed. Service OK.`)));

breaker.on('fallback',
  (data) => $(element).append(
    makeNode(`FALLBACK: ${JSON.stringify(data)}`)));

Promises vs. Callbacks

The opossum API returns a Promise from CircuitBreaker.fire(). But your circuit action - the async function that might fail - doesn't have to return a promise. You can easily turn Node.js style callback functions into something opossum understands by using the built in Node core utility function util.promisify() .

const fs = require('fs');
const { promisify } = require('util');
const CircuitBreaker = require('opossum');

const readFile = promisify(fs.readFile);
const breaker = new CircuitBreaker(readFile, options);

breaker.fire('./package.json', 'utf-8')
  .then(console.log)
  .catch(console.error);

And just for fun, your circuit doesn't even really have to be a function. Not sure when you'd use this - but you could if you wanted to.

const breaker = new CircuitBreaker('foo', options);

breaker.fire()
  .then(console.log) // logs 'foo'
  .catch(console.error);

Typings

Typings are available here.

If you'd like to add them, run npm install @types/opossum in your project.

Metrics

Prometheus

The opossum-prometheus module can be used to produce metrics that are consumable by Prometheus. These metrics include information about the circuit itself, for example how many times it has opened, as well as general Node.js statistics, for example event loop lag.

Hystrix

The opossum-hystrix module can be used to produce metrics that are consumable by the Hystrix Dashboard.

Troubleshooting

You may run into issues related to too many listeners on an EventEmitter like this.

(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 10 unpipe listeners added. Use emitter.setMaxListeners() to increase limit
(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 drain listeners added. Use emitter.setMaxListeners() to increase limit
(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit
(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 close listeners added. Use emitter.setMaxListeners() to increase limit
(node:25619) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 finish listeners added. Use emitter.setMaxListeners() to increase limit

In some cases, seeing this error might indicate a bug in client code, where many CircuitBreakers 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 CircuitBreakers in your app. That's ok.

To get around the error, you can set the number of listeners on the stream.

breaker.stats.getHystrixStream().setMaxListeners(100);

Or it could be that you have a large test suite which exercises some code that creates CircuitBreakers 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.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].