Giter Club home page Giter Club logo

lasier's Introduction

Lasier

A sync/async circuit breaker implementation

Build Status

According to Nygard on your masterpiece book Release It!:

[...] circuit breakers protect overeager gadget hounds from burning their houses down. The principle is the same: detect excess usage, fail first, and open the circuit. More abstractly, the circuit breaker exists to allow one subsystem (an electrical circuit) to fail (excessive current draw, possibly from a short circuit) without destroying the entire system (the house). Furthermore, once the danger has passed, the circuit breaker can be reset to restore full function to the system.

Requirements

  • Python >= 3.7

Instalation

Using pip:

pip install lasier

Usage

To use lasier circuit breaker you'll need a rule and a cache (the circuit state storage) instance

Rule

A Rule is the mechanism that define where circuit will open or close.

MaxFailuresRule

Rule to open circuit based on maximum number of failures

from lasier.circuit_breaker.rules import MaxFailuresRule

rule = MaxFailuresRule(
    max_failures=500,
    failure_cache_key='my_cb'
)
Arguments
Argument Definition
max_failures Maximum number of errors
failure_cache_key Cache key where the number of errors is incremented

PercentageFailuresRule

Rule to open circuit based on a percentage of failures

from lasier.circuit_breaker.rules import PercentageFailuresRule

rule = PercentageFailuresRule(
    max_failures_percentage=60,
    failure_cache_key='my_cb',
    min_accepted_requests=100,
    request_cache_key='my_cb_request'
)
Arguments
Argument Definition
max_failures_percentage Maximum percentage of errors
failure_cache_key Cache key where the number of errors is incremented
min_accepted_requests Minimum number of requests accepted to not open circuit breaker
request_cache_key Cache key where the number of requests is incremented

Circuit Breaker

You can use the Lasier circuit breaker with a context_manager f.ex:

from lasier.circuit_breaker.sync import CircuitBreaker

...

def some_protected_func():
    with CircuitBreaker(
        rule=rule,
        cache=cache,
        failure_exception=ValueError,
        catch_exceptions=(KeyError, TypeError)
    ):
        # some process

Or a decorator, f.ex:

from lasier.circuit_breaker.asyncio import circuit_breaker

...

@circuit_breaker(
    rule=rule,
    cache=cache,
    failure_exception=ValueError,
    catch_exceptions=(KeyError, TypeError)
)
async def some_protected_func():
    # some process

The sync and async implementations follow the same interface, so you only need to change the import path:

  • lasier.circuit_breaker.sync: for sync implementataion
  • lasier.circuit_breaker.asyncio: for async implementataion
Arguments
Argument Definition
rule Instance of class rule.
cache Instance of the circuit breaker state storage.
failure_exception Exception to be raised when it exceeds the maximum number of errors and when the circuit is open.
failure_timeout This value is set on first error. It is used to validate the number of errors by time. (seconds, default 60)
circuit_timeout Time that the circuit will be open. (seconds, default 60)
catch_exceptions List of exceptions catched to increase the number of errors.

WARNING: The args failure_timeout and circuit_timeout will be used on state storage commands so if you'll use libs that expects milliseconds instead of seconds on timeout arguments maybe you'll get yourself in trouble

Circuit state storage

Lasier works with a storage to register the current state of the circuit, number of failures, etc. That storage respects the follow interface:

from lasier.types import Timeout  # Timeout = Optional[Union[int, float]]


class Storage:

    def add(self, key: str, value: int, timeout: Timeout = None) -> None:
        pass

    def set(self, key: str, value: int, timeout: Timeout = None) -> None:
        pass

    def incr(self, key: str) -> int:
        pass

    def get(self, key: str) -> int:
        pass

    def expire(key: str, timeout: Timeout = None) -> None:
        pass

    def delete(self, key: str) -> None:
        pass

    def flushdb(self) -> None:
        pass

For async circuit breaker, lasier works with that same interface however with async syntax, f.ex: async def set(self, key=str, value=int, timeout=Optional[int])

So you can use any cache/storage that respects that interface.

Adapters

If you'll use Lasier with redis-py as cache, you can use lasier.adapters.caches.redis.RedisAdapter

from lasier.adapters.caches import RedisAdapter
from redis import Redis

cache = RedisAdapter(Redis(host='localhost', port=6479, db=0))

Implemented Adapters

Lib Adapter
redis-py lasier.adapters.caches.RedisAdapter
django-cache lasier.adapters.caches.DjangoAdapter
django-cache-async lasier.adapters.caches.DjangoAsyncAdapter
aiocache lasier.adapters.caches.AiocacheAdapter

lasier's People

Contributors

carlosdorneles-mb avatar cassiobotaro avatar deniscapeto avatar dependabot[bot] avatar drgarcia1986 avatar henriquebraga avatar itheodoro avatar jairhenrique avatar renanivo avatar thyagomininelli 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

Watchers

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

lasier's Issues

Documentation

I was planning to start the documentation but i'm not sure if everyone agree on where to host it, readthedocs? suggestions?

Half Open State

To follow the Nygard circuit breaker pattern we need to create the half-open state on the circuit breaker. :

There is now a third state present - half open - meaning the circuit is ready to make a real call as trial to see if the problem is fixed.

source

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.