diff options
Diffstat (limited to 'python-lasier.spec')
-rw-r--r-- | python-lasier.spec | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/python-lasier.spec b/python-lasier.spec new file mode 100644 index 0000000..c420f1b --- /dev/null +++ b/python-lasier.spec @@ -0,0 +1,576 @@ +%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 + +[](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 + +[](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 + +[](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 <Python_Bot@openeuler.org> - 0.3.0-1 +- Package Spec generated |