Package: aiocircuitbreaker
aiocircuitbreakerThis is an async Python implementation of thecircuitbreakerlibrary.InstallationThe project is available on PyPI. Simply run:$ pip install aiocircuitbreakerUsageThis is the simplest example. Just decorate a async function with the@circuitdecorator:from aiocircuitbreaker import circuit

@circuit
async def external_call():
    ...This decorator sets up a circuit breaker with the default settings. The circuit breaker:monitors the function execution and counts failuresresets the failure count after every successful execution (while it is closed)opens and prevents further executions after 5 subsequent failuresswitches to half-open and allows one test-execution after 30 seconds recovery timeoutcloses if the test-execution succeededconsiders all raised exceptions (based on classException) as an expected failureis named “external_call” - the name of the function it decoratesWhat doesfailuremean?Afailureis a raised exception, which was not caught during the function call.
By default, the circuit breaker listens for all exceptions based on the classException.
That means, that all exceptions raised during the function call are considered as an
“expected failure” and will increase the failure count.Get specific about the expected failureIt is important, to beas specific as possible, when defining the expected exception.
The main purpose of a circuit breaker is to protect your distributed system from a cascading failure.
That means, you probably want to open the circuit breaker only, if the integration point on the other
end is unavailable. So e.g. if there is anConnectionErroror a requestTimeout.If you are e.g. using the requests library (http://docs.python-requests.org/) for making HTTP calls,
itsRequestExceptionclass would be a great choice for theexpected_exceptionparameter.All recognized exceptions will be re-raised anyway, but the goal is, to let the circuit breaker only
recognize those exceptions which are related to the communication to your integration point.ConfigurationThe following configuration options can be adjusted via decorator parameters. For example:from aiocircuitbreaker import circuit

@circuit(failure_threshold=10, expected_exception=ConnectionError)
async def external_call():
    ...failure thresholdBy default, the circuit breaker opens after 5 subsequent failures. You can adjust this value with thefailure_thresholdparameter.recovery timeoutBy default, the circuit breaker stays open for 30 seconds to allow the integration point to recover.
You can adjust this value with therecovery_timeoutparameter.expected exceptionBy default, the circuit breaker listens for all exceptions which are based on theExceptionclass.
You can adjust this with theexpected_exceptionparameter. It can be either an exception class or a tuple of exception classes.nameBy default, the circuit breaker name is empty string. You can adjust the name with parametername.fallback functionBy default, the circuit breaker will raise aCircuitBreakerexception when the circuit is opened.
You can instead specify a function (async function) to be called when the circuit is opened. This function can be specified with thefallback_functionparameter and will be called with the same parameters as the decorated function would be.Advanced UsageIf you apply circuit breakers to a couple of functions and you always set specific options other than the default values,
you can extend theCircuitBreakerclass and create your own circuit breaker subclass instead:from aiocircuitbreaker import CircuitBreaker

class MyCircuitBreaker(CircuitBreaker):
    FAILURE_THRESHOLD = 10
    RECOVERY_TIMEOUT = 60
    EXPECTED_EXCEPTION = RequestExceptionNow you have two options to apply your circuit breaker to a function. As an Object directly:@MyCircuitBreaker()
async def external_call():
    ...Please note, that the circuit breaker class has to be initialized, you have to use a class instance as decorator (@MyCircuitBreaker()), not the class itself (@MyCircuitBreaker).Or via the decorator proxy:@circuit(cls=MyCircuitBreaker)
async def external_call():
    ...