%global _empty_manifest_terminate_build 0 Name: python-lasier Version: 0.3.0 Release: 1 Summary: A sync/async circuit breaker implementation License: MIT URL: https://github.com/luizalabs/lasier Source0: https://mirrors.aliyun.com/pypi/web/packages/8c/5d/9672792e0712fbbc5a3d24f9d3128e9ee53ab5a79ba204c14bc352bba679/lasier-0.3.0.tar.gz BuildArch: noarch %description # Lasier A sync/async circuit breaker implementation [![Build Status](https://github.com/luizalabs/lasier/actions/workflows/main.yaml/badge.svg)](https://github.com/luizalabs/lasier/actions) According to Nygard on your masterpiece book [Release It!](http://pragprog.com/titles/mnee/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 ```python 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 ```python 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: ```python 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: ```python 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](https://github.com/luizalabs/lasier#rule). | | cache | Instance of the circuit breaker [state storage](https://github.com/luizalabs/lasier#circuit-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: ```python 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](https://github.com/andymccurdy/redis-py) as cache, you can use `lasier.adapters.caches.redis.RedisAdapter` ```python 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` | %package -n python3-lasier Summary: A sync/async circuit breaker implementation Provides: python-lasier BuildRequires: python3-devel BuildRequires: python3-setuptools BuildRequires: python3-pip %description -n python3-lasier # Lasier A sync/async circuit breaker implementation [![Build Status](https://github.com/luizalabs/lasier/actions/workflows/main.yaml/badge.svg)](https://github.com/luizalabs/lasier/actions) According to Nygard on your masterpiece book [Release It!](http://pragprog.com/titles/mnee/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 ```python 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 ```python 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: ```python 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: ```python 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](https://github.com/luizalabs/lasier#rule). | | cache | Instance of the circuit breaker [state storage](https://github.com/luizalabs/lasier#circuit-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: ```python 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](https://github.com/andymccurdy/redis-py) as cache, you can use `lasier.adapters.caches.redis.RedisAdapter` ```python 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` | %package help Summary: Development documents and examples for lasier Provides: python3-lasier-doc %description help # Lasier A sync/async circuit breaker implementation [![Build Status](https://github.com/luizalabs/lasier/actions/workflows/main.yaml/badge.svg)](https://github.com/luizalabs/lasier/actions) According to Nygard on your masterpiece book [Release It!](http://pragprog.com/titles/mnee/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 ```python 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 ```python 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: ```python 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: ```python 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](https://github.com/luizalabs/lasier#rule). | | cache | Instance of the circuit breaker [state storage](https://github.com/luizalabs/lasier#circuit-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: ```python 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](https://github.com/andymccurdy/redis-py) as cache, you can use `lasier.adapters.caches.redis.RedisAdapter` ```python 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` | %prep %autosetup -n lasier-0.3.0 %build %py3_build %install %py3_install install -d -m755 %{buildroot}/%{_pkgdocdir} if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/lib64 ]; then find usr/lib64 -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/bin ]; then find usr/bin -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/sbin ]; then find usr/sbin -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi touch doclist.lst if [ -d usr/share/man ]; then find usr/share/man -type f -printf "\"/%h/%f.gz\"\n" >> doclist.lst fi popd mv %{buildroot}/filelist.lst . mv %{buildroot}/doclist.lst . %files -n python3-lasier -f filelist.lst %dir %{python3_sitelib}/* %files help -f doclist.lst %{_docdir}/* %changelog * Tue Jun 20 2023 Python_Bot - 0.3.0-1 - Package Spec generated