dory-processor-sdk 0.0.1__py3-none-any.whl
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.
- dory/__init__.py +101 -0
- dory/auth/__init__.py +10 -0
- dory/auth/oauth2.py +153 -0
- dory/auto_instrument.py +142 -0
- dory/cli/__init__.py +5 -0
- dory/cli/main.py +137 -0
- dory/cli/templates.py +123 -0
- dory/config/__init__.py +23 -0
- dory/config/defaults.py +24 -0
- dory/config/loader.py +430 -0
- dory/config/presets.py +73 -0
- dory/config/schema.py +84 -0
- dory/core/__init__.py +27 -0
- dory/core/app.py +434 -0
- dory/core/context.py +209 -0
- dory/core/lifecycle.py +214 -0
- dory/core/meta.py +121 -0
- dory/core/modes.py +479 -0
- dory/core/processor.py +564 -0
- dory/core/signals.py +122 -0
- dory/decorators.py +142 -0
- dory/edge/__init__.py +88 -0
- dory/edge/adaptive.py +644 -0
- dory/edge/detector.py +546 -0
- dory/edge/fencing.py +488 -0
- dory/edge/heartbeat.py +598 -0
- dory/edge/role.py +419 -0
- dory/errors/__init__.py +139 -0
- dory/errors/classification.py +362 -0
- dory/errors/codes.py +498 -0
- dory/geo/__init__.py +40 -0
- dory/geo/geolocalizer.py +1034 -0
- dory/health/__init__.py +12 -0
- dory/health/probes.py +210 -0
- dory/health/server.py +635 -0
- dory/k8s/__init__.py +80 -0
- dory/k8s/annotation_watcher.py +184 -0
- dory/k8s/client.py +251 -0
- dory/k8s/labels.py +505 -0
- dory/k8s/pod_metadata.py +182 -0
- dory/logging/__init__.py +9 -0
- dory/logging/logger.py +148 -0
- dory/metrics/__init__.py +7 -0
- dory/metrics/collector.py +301 -0
- dory/middleware/__init__.py +46 -0
- dory/middleware/connection_tracker.py +608 -0
- dory/middleware/request_id.py +325 -0
- dory/middleware/request_tracker.py +511 -0
- dory/migration/__init__.py +33 -0
- dory/migration/configmap.py +232 -0
- dory/migration/s3_store.py +594 -0
- dory/migration/serialization.py +135 -0
- dory/migration/state_manager.py +286 -0
- dory/migration/transfer.py +382 -0
- dory/monitoring/__init__.py +29 -0
- dory/monitoring/opentelemetry.py +489 -0
- dory/output/__init__.py +31 -0
- dory/output/envelope.py +137 -0
- dory/output/formatter.py +113 -0
- dory/output/rabbitmq.py +632 -0
- dory/output/routing.py +318 -0
- dory/output/validator.py +199 -0
- dory/py.typed +2 -0
- dory/recovery/__init__.py +60 -0
- dory/recovery/golden_image.py +487 -0
- dory/recovery/golden_snapshot.py +713 -0
- dory/recovery/golden_validator.py +518 -0
- dory/recovery/partial_recovery.py +482 -0
- dory/recovery/recovery_decision.py +242 -0
- dory/recovery/restart_detector.py +142 -0
- dory/recovery/state_validator.py +183 -0
- dory/resilience/__init__.py +45 -0
- dory/resilience/circuit_breaker.py +457 -0
- dory/resilience/retry.py +389 -0
- dory/simple.py +342 -0
- dory/types.py +68 -0
- dory/utils/__init__.py +31 -0
- dory/utils/errors.py +59 -0
- dory/utils/retry.py +115 -0
- dory/utils/timeout.py +80 -0
- dory_processor_sdk-0.0.1.dist-info/METADATA +424 -0
- dory_processor_sdk-0.0.1.dist-info/RECORD +86 -0
- dory_processor_sdk-0.0.1.dist-info/WHEEL +5 -0
- dory_processor_sdk-0.0.1.dist-info/entry_points.txt +2 -0
- dory_processor_sdk-0.0.1.dist-info/licenses/LICENSE +201 -0
- dory_processor_sdk-0.0.1.dist-info/top_level.txt +1 -0
dory/health/__init__.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Health check and metrics HTTP server."""
|
|
2
|
+
|
|
3
|
+
from dory.health.server import HealthServer
|
|
4
|
+
from dory.health.probes import LivenessProbe, ReadinessProbe, ProbeResult, StartupProbe
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"HealthServer",
|
|
8
|
+
"LivenessProbe",
|
|
9
|
+
"ReadinessProbe",
|
|
10
|
+
"ProbeResult",
|
|
11
|
+
"StartupProbe",
|
|
12
|
+
]
|
dory/health/probes.py
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Health probe implementations.
|
|
3
|
+
|
|
4
|
+
Provides liveness and readiness probes for Kubernetes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import inspect
|
|
9
|
+
import logging
|
|
10
|
+
from abc import ABC, abstractmethod
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Callable, Awaitable, Union
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class ProbeResult:
|
|
19
|
+
"""Result of a health probe check."""
|
|
20
|
+
healthy: bool
|
|
21
|
+
message: str = ""
|
|
22
|
+
details: dict = field(default_factory=dict)
|
|
23
|
+
|
|
24
|
+
def to_dict(self) -> dict:
|
|
25
|
+
"""Convert to dictionary for JSON response."""
|
|
26
|
+
return {
|
|
27
|
+
"healthy": self.healthy,
|
|
28
|
+
"message": self.message,
|
|
29
|
+
"details": self.details,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class HealthProbe(ABC):
|
|
34
|
+
"""Abstract base class for health probes."""
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
async def check(self) -> ProbeResult:
|
|
38
|
+
"""
|
|
39
|
+
Perform health check.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
ProbeResult indicating health status
|
|
43
|
+
"""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class LivenessProbe(HealthProbe):
|
|
48
|
+
"""
|
|
49
|
+
Liveness probe for Kubernetes.
|
|
50
|
+
|
|
51
|
+
Indicates whether the process is alive and should not be killed.
|
|
52
|
+
Failed liveness = Kubernetes restarts the pod.
|
|
53
|
+
|
|
54
|
+
Should be lightweight and always pass unless process is deadlocked.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__(self):
|
|
58
|
+
"""Initialize liveness probe."""
|
|
59
|
+
self._custom_checks: list[Callable[[], Union[bool, Awaitable[bool]]]] = []
|
|
60
|
+
|
|
61
|
+
def add_check(self, check: Callable[[], Union[bool, Awaitable[bool]]]) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Add custom liveness check.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
check: Sync or async function returning True if healthy
|
|
67
|
+
"""
|
|
68
|
+
self._custom_checks.append(check)
|
|
69
|
+
|
|
70
|
+
async def check(self) -> ProbeResult:
|
|
71
|
+
"""
|
|
72
|
+
Perform liveness check.
|
|
73
|
+
|
|
74
|
+
Default implementation always returns healthy.
|
|
75
|
+
Override or add custom checks for specific requirements.
|
|
76
|
+
"""
|
|
77
|
+
# Run custom checks
|
|
78
|
+
for i, custom_check in enumerate(self._custom_checks):
|
|
79
|
+
try:
|
|
80
|
+
# Handle both sync and async functions
|
|
81
|
+
if asyncio.iscoroutinefunction(custom_check):
|
|
82
|
+
result = await custom_check()
|
|
83
|
+
else:
|
|
84
|
+
result = custom_check()
|
|
85
|
+
|
|
86
|
+
if not result:
|
|
87
|
+
return ProbeResult(
|
|
88
|
+
healthy=False,
|
|
89
|
+
message=f"Custom liveness check {i} failed",
|
|
90
|
+
)
|
|
91
|
+
except Exception as e:
|
|
92
|
+
logger.error(f"Liveness check {i} error: {e}")
|
|
93
|
+
return ProbeResult(
|
|
94
|
+
healthy=False,
|
|
95
|
+
message=f"Custom liveness check {i} error: {e}",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
return ProbeResult(healthy=True, message="Process is alive")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class ReadinessProbe(HealthProbe):
|
|
102
|
+
"""
|
|
103
|
+
Readiness probe for Kubernetes.
|
|
104
|
+
|
|
105
|
+
Indicates whether the process is ready to receive traffic.
|
|
106
|
+
Failed readiness = Kubernetes removes pod from service endpoints.
|
|
107
|
+
|
|
108
|
+
Should check that all dependencies are available.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def __init__(self):
|
|
112
|
+
"""Initialize readiness probe."""
|
|
113
|
+
self._ready = False
|
|
114
|
+
self._custom_checks: list[Callable[[], Union[bool, Awaitable[bool]]]] = []
|
|
115
|
+
|
|
116
|
+
def mark_ready(self) -> None:
|
|
117
|
+
"""Mark the processor as ready to receive traffic."""
|
|
118
|
+
self._ready = True
|
|
119
|
+
logger.info("Processor marked as ready")
|
|
120
|
+
|
|
121
|
+
def mark_not_ready(self) -> None:
|
|
122
|
+
"""Mark the processor as not ready."""
|
|
123
|
+
self._ready = False
|
|
124
|
+
logger.info("Processor marked as not ready")
|
|
125
|
+
|
|
126
|
+
def is_ready(self) -> bool:
|
|
127
|
+
"""Check if currently marked as ready."""
|
|
128
|
+
return self._ready
|
|
129
|
+
|
|
130
|
+
def add_check(self, check: Callable[[], Union[bool, Awaitable[bool]]]) -> None:
|
|
131
|
+
"""
|
|
132
|
+
Add custom readiness check.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
check: Sync or async function returning True if ready
|
|
136
|
+
"""
|
|
137
|
+
self._custom_checks.append(check)
|
|
138
|
+
|
|
139
|
+
async def check(self) -> ProbeResult:
|
|
140
|
+
"""
|
|
141
|
+
Perform readiness check.
|
|
142
|
+
|
|
143
|
+
Returns not ready until explicitly marked ready.
|
|
144
|
+
Also runs any custom checks.
|
|
145
|
+
"""
|
|
146
|
+
if not self._ready:
|
|
147
|
+
return ProbeResult(
|
|
148
|
+
healthy=False,
|
|
149
|
+
message="Processor not yet ready",
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Run custom checks
|
|
153
|
+
for i, custom_check in enumerate(self._custom_checks):
|
|
154
|
+
try:
|
|
155
|
+
# Handle both sync and async functions
|
|
156
|
+
if asyncio.iscoroutinefunction(custom_check):
|
|
157
|
+
result = await custom_check()
|
|
158
|
+
else:
|
|
159
|
+
result = custom_check()
|
|
160
|
+
|
|
161
|
+
if not result:
|
|
162
|
+
return ProbeResult(
|
|
163
|
+
healthy=False,
|
|
164
|
+
message=f"Custom readiness check {i} failed",
|
|
165
|
+
)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
logger.error(f"Readiness check {i} error: {e}")
|
|
168
|
+
return ProbeResult(
|
|
169
|
+
healthy=False,
|
|
170
|
+
message=f"Custom readiness check {i} error: {e}",
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
return ProbeResult(healthy=True, message="Processor is ready")
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class StartupProbe(HealthProbe):
|
|
177
|
+
"""
|
|
178
|
+
Startup probe for Kubernetes.
|
|
179
|
+
|
|
180
|
+
Indicates whether the application has finished starting up.
|
|
181
|
+
Failed startup = Kubernetes keeps waiting (up to failureThreshold).
|
|
182
|
+
|
|
183
|
+
Useful for slow-starting applications.
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
def __init__(self, startup_complete_check: Callable[[], bool] | None = None):
|
|
187
|
+
"""
|
|
188
|
+
Initialize startup probe.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
startup_complete_check: Function returning True when startup is complete
|
|
192
|
+
"""
|
|
193
|
+
self._startup_complete = False
|
|
194
|
+
self._startup_check = startup_complete_check
|
|
195
|
+
|
|
196
|
+
def mark_startup_complete(self) -> None:
|
|
197
|
+
"""Mark startup as complete."""
|
|
198
|
+
self._startup_complete = True
|
|
199
|
+
logger.info("Startup marked as complete")
|
|
200
|
+
|
|
201
|
+
async def check(self) -> ProbeResult:
|
|
202
|
+
"""Perform startup check."""
|
|
203
|
+
if self._startup_complete:
|
|
204
|
+
return ProbeResult(healthy=True, message="Startup complete")
|
|
205
|
+
|
|
206
|
+
if self._startup_check and self._startup_check():
|
|
207
|
+
self._startup_complete = True
|
|
208
|
+
return ProbeResult(healthy=True, message="Startup complete")
|
|
209
|
+
|
|
210
|
+
return ProbeResult(healthy=False, message="Still starting up")
|