summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--python-lasier.spec576
-rw-r--r--sources1
3 files changed, 578 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..b301bfb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/lasier-0.3.0.tar.gz
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
+
+[![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 <Python_Bot@openeuler.org> - 0.3.0-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..856e9f1
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+a9e3e1be3bfb30f21b14c10428c5c5ef lasier-0.3.0.tar.gz