Skip to main content

A sync/async circuit breaker implementation

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lasier-0.3.0.tar.gz (9.2 kB view details)

Uploaded Source

Built Distribution

lasier-0.3.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file lasier-0.3.0.tar.gz.

File metadata

  • Download URL: lasier-0.3.0.tar.gz
  • Upload date:
  • Size: 9.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.14 CPython/3.7.13 Linux/5.15.0-1014-azure

File hashes

Hashes for lasier-0.3.0.tar.gz
Algorithm Hash digest
SHA256 03d5a8058adc1ff1f0d17f9e544b946bd8c6d7256dfe120288022677fc2db8ce
MD5 a9e3e1be3bfb30f21b14c10428c5c5ef
BLAKE2b-256 8c5d9672792e0712fbbc5a3d24f9d3128e9ee53ab5a79ba204c14bc352bba679

See more details on using hashes here.

File details

Details for the file lasier-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: lasier-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.14 CPython/3.7.13 Linux/5.15.0-1014-azure

File hashes

Hashes for lasier-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 68a8218aead4a9b1ad33aaed9085575dcc128076432a0d6837cfbf214ff958f9
MD5 5ba960f46f477d1c3477a7ca9850eb6c
BLAKE2b-256 97991437761145080028c5a2363b23326e3140e16f10226c53fccae0269e1f42

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page