advanced-systems 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- advanced_systems-1.0.0/PKG-INFO +53 -0
- advanced_systems-1.0.0/README.md +42 -0
- advanced_systems-1.0.0/pyproject.toml +17 -0
- advanced_systems-1.0.0/setup.cfg +4 -0
- advanced_systems-1.0.0/src/__init__.py +1 -0
- advanced_systems-1.0.0/src/advanced_systems.egg-info/PKG-INFO +53 -0
- advanced_systems-1.0.0/src/advanced_systems.egg-info/SOURCES.txt +10 -0
- advanced_systems-1.0.0/src/advanced_systems.egg-info/dependency_links.txt +1 -0
- advanced_systems-1.0.0/src/advanced_systems.egg-info/requires.txt +3 -0
- advanced_systems-1.0.0/src/advanced_systems.egg-info/top_level.txt +2 -0
- advanced_systems-1.0.0/src/resilience/__init__.py +1 -0
- advanced_systems-1.0.0/src/resilience/circuit_breaker.py +222 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: advanced-systems
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Advanced patterns and resilience
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: pydantic>=2.5.0
|
|
9
|
+
Requires-Dist: tenacity>=8.2.0
|
|
10
|
+
Requires-Dist: structlog>=24.1.0
|
|
11
|
+
|
|
12
|
+
# 11_advanced_systems - Patterns & Resilience
|
|
13
|
+
|
|
14
|
+
> Production-grade advanced patterns demonstrating circuit breakers, rule engines, and resilience patterns.
|
|
15
|
+
|
|
16
|
+
## 🎯 Overview
|
|
17
|
+
|
|
18
|
+
This module implements:
|
|
19
|
+
|
|
20
|
+
- **Circuit Breaker** - Fault tolerance pattern
|
|
21
|
+
- **Rule Engine** - Business rules execution
|
|
22
|
+
- **Rate Limiter** - Request throttling
|
|
23
|
+
- **Retry with Backoff** - Transient failure handling
|
|
24
|
+
- **Bulkhead** - Resource isolation
|
|
25
|
+
|
|
26
|
+
## 📁 Structure
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
11_advanced_systems/
|
|
30
|
+
├── src/
|
|
31
|
+
│ ├── resilience/ # Resilience patterns
|
|
32
|
+
│ │ ├── circuit_breaker.py
|
|
33
|
+
│ │ ├── rate_limiter.py
|
|
34
|
+
│ │ ├── retry.py
|
|
35
|
+
│ │ └── bulkhead.py
|
|
36
|
+
│ ├── rules/ # Rule engine
|
|
37
|
+
│ │ ├── engine.py # Rule execution
|
|
38
|
+
│ │ └── dsl.py # Rule DSL
|
|
39
|
+
│ └── caching/ # Caching patterns
|
|
40
|
+
├── tests/ # Test suite
|
|
41
|
+
└── pyproject.toml # Dependencies
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 🚀 Quick Start
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install -e .
|
|
48
|
+
python -m src.main
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 📄 License
|
|
52
|
+
|
|
53
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# 11_advanced_systems - Patterns & Resilience
|
|
2
|
+
|
|
3
|
+
> Production-grade advanced patterns demonstrating circuit breakers, rule engines, and resilience patterns.
|
|
4
|
+
|
|
5
|
+
## 🎯 Overview
|
|
6
|
+
|
|
7
|
+
This module implements:
|
|
8
|
+
|
|
9
|
+
- **Circuit Breaker** - Fault tolerance pattern
|
|
10
|
+
- **Rule Engine** - Business rules execution
|
|
11
|
+
- **Rate Limiter** - Request throttling
|
|
12
|
+
- **Retry with Backoff** - Transient failure handling
|
|
13
|
+
- **Bulkhead** - Resource isolation
|
|
14
|
+
|
|
15
|
+
## 📁 Structure
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
11_advanced_systems/
|
|
19
|
+
├── src/
|
|
20
|
+
│ ├── resilience/ # Resilience patterns
|
|
21
|
+
│ │ ├── circuit_breaker.py
|
|
22
|
+
│ │ ├── rate_limiter.py
|
|
23
|
+
│ │ ├── retry.py
|
|
24
|
+
│ │ └── bulkhead.py
|
|
25
|
+
│ ├── rules/ # Rule engine
|
|
26
|
+
│ │ ├── engine.py # Rule execution
|
|
27
|
+
│ │ └── dsl.py # Rule DSL
|
|
28
|
+
│ └── caching/ # Caching patterns
|
|
29
|
+
├── tests/ # Test suite
|
|
30
|
+
└── pyproject.toml # Dependencies
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 🚀 Quick Start
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install -e .
|
|
37
|
+
python -m src.main
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 📄 License
|
|
41
|
+
|
|
42
|
+
MIT
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "advanced-systems"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = "Advanced patterns and resilience"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = {text = "MIT"}
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
"pydantic>=2.5.0",
|
|
11
|
+
"tenacity>=8.2.0",
|
|
12
|
+
"structlog>=24.1.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[build-system]
|
|
16
|
+
requires = ["setuptools>=68.0"]
|
|
17
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Advanced Systems Module."""
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: advanced-systems
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Advanced patterns and resilience
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: pydantic>=2.5.0
|
|
9
|
+
Requires-Dist: tenacity>=8.2.0
|
|
10
|
+
Requires-Dist: structlog>=24.1.0
|
|
11
|
+
|
|
12
|
+
# 11_advanced_systems - Patterns & Resilience
|
|
13
|
+
|
|
14
|
+
> Production-grade advanced patterns demonstrating circuit breakers, rule engines, and resilience patterns.
|
|
15
|
+
|
|
16
|
+
## 🎯 Overview
|
|
17
|
+
|
|
18
|
+
This module implements:
|
|
19
|
+
|
|
20
|
+
- **Circuit Breaker** - Fault tolerance pattern
|
|
21
|
+
- **Rule Engine** - Business rules execution
|
|
22
|
+
- **Rate Limiter** - Request throttling
|
|
23
|
+
- **Retry with Backoff** - Transient failure handling
|
|
24
|
+
- **Bulkhead** - Resource isolation
|
|
25
|
+
|
|
26
|
+
## 📁 Structure
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
11_advanced_systems/
|
|
30
|
+
├── src/
|
|
31
|
+
│ ├── resilience/ # Resilience patterns
|
|
32
|
+
│ │ ├── circuit_breaker.py
|
|
33
|
+
│ │ ├── rate_limiter.py
|
|
34
|
+
│ │ ├── retry.py
|
|
35
|
+
│ │ └── bulkhead.py
|
|
36
|
+
│ ├── rules/ # Rule engine
|
|
37
|
+
│ │ ├── engine.py # Rule execution
|
|
38
|
+
│ │ └── dsl.py # Rule DSL
|
|
39
|
+
│ └── caching/ # Caching patterns
|
|
40
|
+
├── tests/ # Test suite
|
|
41
|
+
└── pyproject.toml # Dependencies
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 🚀 Quick Start
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install -e .
|
|
48
|
+
python -m src.main
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 📄 License
|
|
52
|
+
|
|
53
|
+
MIT
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/__init__.py
|
|
4
|
+
src/advanced_systems.egg-info/PKG-INFO
|
|
5
|
+
src/advanced_systems.egg-info/SOURCES.txt
|
|
6
|
+
src/advanced_systems.egg-info/dependency_links.txt
|
|
7
|
+
src/advanced_systems.egg-info/requires.txt
|
|
8
|
+
src/advanced_systems.egg-info/top_level.txt
|
|
9
|
+
src/resilience/__init__.py
|
|
10
|
+
src/resilience/circuit_breaker.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Resilience patterns package."""
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Circuit Breaker - Fault tolerance pattern implementation.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import time
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from functools import wraps
|
|
11
|
+
from typing import Any, Callable, Optional, TypeVar
|
|
12
|
+
|
|
13
|
+
import structlog
|
|
14
|
+
|
|
15
|
+
logger = structlog.get_logger(__name__)
|
|
16
|
+
|
|
17
|
+
F = TypeVar("F", bound=Callable[..., Any])
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CircuitState(str, Enum):
|
|
21
|
+
"""Circuit breaker states."""
|
|
22
|
+
|
|
23
|
+
CLOSED = "closed" # Normal operation
|
|
24
|
+
OPEN = "open" # Failing, reject requests
|
|
25
|
+
HALF_OPEN = "half_open" # Testing recovery
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class CircuitBreakerConfig:
|
|
30
|
+
"""Circuit breaker configuration."""
|
|
31
|
+
|
|
32
|
+
failure_threshold: int = 5
|
|
33
|
+
success_threshold: int = 2
|
|
34
|
+
timeout_seconds: float = 30.0
|
|
35
|
+
half_open_max_calls: int = 3
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class CircuitBreakerState:
|
|
40
|
+
"""Internal circuit breaker state."""
|
|
41
|
+
|
|
42
|
+
state: CircuitState = CircuitState.CLOSED
|
|
43
|
+
failure_count: int = 0
|
|
44
|
+
success_count: int = 0
|
|
45
|
+
last_failure_time: Optional[float] = None
|
|
46
|
+
half_open_calls: int = 0
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class CircuitBreaker:
|
|
50
|
+
"""
|
|
51
|
+
Circuit breaker pattern implementation.
|
|
52
|
+
|
|
53
|
+
Prevents cascading failures by failing fast when
|
|
54
|
+
a service is unhealthy.
|
|
55
|
+
|
|
56
|
+
Usage:
|
|
57
|
+
circuit = CircuitBreaker("user-service")
|
|
58
|
+
|
|
59
|
+
@circuit.protect
|
|
60
|
+
async def call_user_service():
|
|
61
|
+
return await http_client.get("/users")
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
name: str,
|
|
67
|
+
config: Optional[CircuitBreakerConfig] = None,
|
|
68
|
+
):
|
|
69
|
+
"""
|
|
70
|
+
Initialize circuit breaker.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
name: Circuit name for logging
|
|
74
|
+
config: Optional configuration
|
|
75
|
+
"""
|
|
76
|
+
self.name = name
|
|
77
|
+
self.config = config or CircuitBreakerConfig()
|
|
78
|
+
self._state = CircuitBreakerState()
|
|
79
|
+
self._lock = asyncio.Lock()
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def state(self) -> CircuitState:
|
|
83
|
+
"""Get current circuit state."""
|
|
84
|
+
return self._state.state
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def is_closed(self) -> bool:
|
|
88
|
+
"""Check if circuit is closed (normal)."""
|
|
89
|
+
return self._state.state == CircuitState.CLOSED
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def is_open(self) -> bool:
|
|
93
|
+
"""Check if circuit is open (failing)."""
|
|
94
|
+
return self._state.state == CircuitState.OPEN
|
|
95
|
+
|
|
96
|
+
async def _should_allow_request(self) -> bool:
|
|
97
|
+
"""Determine if request should be allowed."""
|
|
98
|
+
async with self._lock:
|
|
99
|
+
if self._state.state == CircuitState.CLOSED:
|
|
100
|
+
return True
|
|
101
|
+
|
|
102
|
+
if self._state.state == CircuitState.OPEN:
|
|
103
|
+
# Check if timeout has passed
|
|
104
|
+
if self._state.last_failure_time:
|
|
105
|
+
elapsed = time.time() - self._state.last_failure_time
|
|
106
|
+
if elapsed >= self.config.timeout_seconds:
|
|
107
|
+
self._transition_to_half_open()
|
|
108
|
+
return True
|
|
109
|
+
return False
|
|
110
|
+
|
|
111
|
+
# Half-open: allow limited requests
|
|
112
|
+
if self._state.half_open_calls < self.config.half_open_max_calls:
|
|
113
|
+
self._state.half_open_calls += 1
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
async def _record_success(self) -> None:
|
|
119
|
+
"""Record successful call."""
|
|
120
|
+
async with self._lock:
|
|
121
|
+
if self._state.state == CircuitState.HALF_OPEN:
|
|
122
|
+
self._state.success_count += 1
|
|
123
|
+
if self._state.success_count >= self.config.success_threshold:
|
|
124
|
+
self._transition_to_closed()
|
|
125
|
+
elif self._state.state == CircuitState.CLOSED:
|
|
126
|
+
# Reset failure count on success
|
|
127
|
+
self._state.failure_count = 0
|
|
128
|
+
|
|
129
|
+
async def _record_failure(self, error: Exception) -> None:
|
|
130
|
+
"""Record failed call."""
|
|
131
|
+
async with self._lock:
|
|
132
|
+
self._state.failure_count += 1
|
|
133
|
+
self._state.last_failure_time = time.time()
|
|
134
|
+
|
|
135
|
+
logger.warning(
|
|
136
|
+
"circuit_breaker_failure",
|
|
137
|
+
circuit=self.name,
|
|
138
|
+
failure_count=self._state.failure_count,
|
|
139
|
+
error=str(error),
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if self._state.state == CircuitState.HALF_OPEN:
|
|
143
|
+
self._transition_to_open()
|
|
144
|
+
elif self._state.state == CircuitState.CLOSED:
|
|
145
|
+
if self._state.failure_count >= self.config.failure_threshold:
|
|
146
|
+
self._transition_to_open()
|
|
147
|
+
|
|
148
|
+
def _transition_to_open(self) -> None:
|
|
149
|
+
"""Transition to open state."""
|
|
150
|
+
logger.warning("circuit_breaker_opened", circuit=self.name)
|
|
151
|
+
self._state.state = CircuitState.OPEN
|
|
152
|
+
self._state.success_count = 0
|
|
153
|
+
self._state.half_open_calls = 0
|
|
154
|
+
|
|
155
|
+
def _transition_to_half_open(self) -> None:
|
|
156
|
+
"""Transition to half-open state."""
|
|
157
|
+
logger.info("circuit_breaker_half_open", circuit=self.name)
|
|
158
|
+
self._state.state = CircuitState.HALF_OPEN
|
|
159
|
+
self._state.half_open_calls = 0
|
|
160
|
+
self._state.success_count = 0
|
|
161
|
+
|
|
162
|
+
def _transition_to_closed(self) -> None:
|
|
163
|
+
"""Transition to closed state."""
|
|
164
|
+
logger.info("circuit_breaker_closed", circuit=self.name)
|
|
165
|
+
self._state.state = CircuitState.CLOSED
|
|
166
|
+
self._state.failure_count = 0
|
|
167
|
+
self._state.success_count = 0
|
|
168
|
+
|
|
169
|
+
def protect(self, func: F) -> F:
|
|
170
|
+
"""
|
|
171
|
+
Decorator to protect a function with circuit breaker.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
func: Async function to protect
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
Protected function
|
|
178
|
+
"""
|
|
179
|
+
@wraps(func)
|
|
180
|
+
async def wrapper(*args, **kwargs):
|
|
181
|
+
if not await self._should_allow_request():
|
|
182
|
+
raise CircuitBreakerOpen(
|
|
183
|
+
f"Circuit '{self.name}' is open"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
result = await func(*args, **kwargs)
|
|
188
|
+
await self._record_success()
|
|
189
|
+
return result
|
|
190
|
+
except Exception as e:
|
|
191
|
+
await self._record_failure(e)
|
|
192
|
+
raise
|
|
193
|
+
|
|
194
|
+
return wrapper # type: ignore
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class CircuitBreakerOpen(Exception):
|
|
198
|
+
"""Raised when circuit breaker is open."""
|
|
199
|
+
pass
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
# Registry for circuit breakers
|
|
203
|
+
_circuits: dict[str, CircuitBreaker] = {}
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def get_circuit_breaker(
|
|
207
|
+
name: str,
|
|
208
|
+
config: Optional[CircuitBreakerConfig] = None,
|
|
209
|
+
) -> CircuitBreaker:
|
|
210
|
+
"""
|
|
211
|
+
Get or create a circuit breaker.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
name: Circuit name
|
|
215
|
+
config: Optional configuration
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Circuit breaker instance
|
|
219
|
+
"""
|
|
220
|
+
if name not in _circuits:
|
|
221
|
+
_circuits[name] = CircuitBreaker(name, config)
|
|
222
|
+
return _circuits[name]
|