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.
Files changed (86) hide show
  1. dory/__init__.py +101 -0
  2. dory/auth/__init__.py +10 -0
  3. dory/auth/oauth2.py +153 -0
  4. dory/auto_instrument.py +142 -0
  5. dory/cli/__init__.py +5 -0
  6. dory/cli/main.py +137 -0
  7. dory/cli/templates.py +123 -0
  8. dory/config/__init__.py +23 -0
  9. dory/config/defaults.py +24 -0
  10. dory/config/loader.py +430 -0
  11. dory/config/presets.py +73 -0
  12. dory/config/schema.py +84 -0
  13. dory/core/__init__.py +27 -0
  14. dory/core/app.py +434 -0
  15. dory/core/context.py +209 -0
  16. dory/core/lifecycle.py +214 -0
  17. dory/core/meta.py +121 -0
  18. dory/core/modes.py +479 -0
  19. dory/core/processor.py +564 -0
  20. dory/core/signals.py +122 -0
  21. dory/decorators.py +142 -0
  22. dory/edge/__init__.py +88 -0
  23. dory/edge/adaptive.py +644 -0
  24. dory/edge/detector.py +546 -0
  25. dory/edge/fencing.py +488 -0
  26. dory/edge/heartbeat.py +598 -0
  27. dory/edge/role.py +419 -0
  28. dory/errors/__init__.py +139 -0
  29. dory/errors/classification.py +362 -0
  30. dory/errors/codes.py +498 -0
  31. dory/geo/__init__.py +40 -0
  32. dory/geo/geolocalizer.py +1034 -0
  33. dory/health/__init__.py +12 -0
  34. dory/health/probes.py +210 -0
  35. dory/health/server.py +635 -0
  36. dory/k8s/__init__.py +80 -0
  37. dory/k8s/annotation_watcher.py +184 -0
  38. dory/k8s/client.py +251 -0
  39. dory/k8s/labels.py +505 -0
  40. dory/k8s/pod_metadata.py +182 -0
  41. dory/logging/__init__.py +9 -0
  42. dory/logging/logger.py +148 -0
  43. dory/metrics/__init__.py +7 -0
  44. dory/metrics/collector.py +301 -0
  45. dory/middleware/__init__.py +46 -0
  46. dory/middleware/connection_tracker.py +608 -0
  47. dory/middleware/request_id.py +325 -0
  48. dory/middleware/request_tracker.py +511 -0
  49. dory/migration/__init__.py +33 -0
  50. dory/migration/configmap.py +232 -0
  51. dory/migration/s3_store.py +594 -0
  52. dory/migration/serialization.py +135 -0
  53. dory/migration/state_manager.py +286 -0
  54. dory/migration/transfer.py +382 -0
  55. dory/monitoring/__init__.py +29 -0
  56. dory/monitoring/opentelemetry.py +489 -0
  57. dory/output/__init__.py +31 -0
  58. dory/output/envelope.py +137 -0
  59. dory/output/formatter.py +113 -0
  60. dory/output/rabbitmq.py +632 -0
  61. dory/output/routing.py +318 -0
  62. dory/output/validator.py +199 -0
  63. dory/py.typed +2 -0
  64. dory/recovery/__init__.py +60 -0
  65. dory/recovery/golden_image.py +487 -0
  66. dory/recovery/golden_snapshot.py +713 -0
  67. dory/recovery/golden_validator.py +518 -0
  68. dory/recovery/partial_recovery.py +482 -0
  69. dory/recovery/recovery_decision.py +242 -0
  70. dory/recovery/restart_detector.py +142 -0
  71. dory/recovery/state_validator.py +183 -0
  72. dory/resilience/__init__.py +45 -0
  73. dory/resilience/circuit_breaker.py +457 -0
  74. dory/resilience/retry.py +389 -0
  75. dory/simple.py +342 -0
  76. dory/types.py +68 -0
  77. dory/utils/__init__.py +31 -0
  78. dory/utils/errors.py +59 -0
  79. dory/utils/retry.py +115 -0
  80. dory/utils/timeout.py +80 -0
  81. dory_processor_sdk-0.0.1.dist-info/METADATA +424 -0
  82. dory_processor_sdk-0.0.1.dist-info/RECORD +86 -0
  83. dory_processor_sdk-0.0.1.dist-info/WHEEL +5 -0
  84. dory_processor_sdk-0.0.1.dist-info/entry_points.txt +2 -0
  85. dory_processor_sdk-0.0.1.dist-info/licenses/LICENSE +201 -0
  86. dory_processor_sdk-0.0.1.dist-info/top_level.txt +1 -0
dory/errors/codes.py ADDED
@@ -0,0 +1,498 @@
1
+ """
2
+ Structured Error Code System for Dory SDK
3
+
4
+ This module defines a comprehensive error code system for the Dory SDK,
5
+ providing structured, searchable error codes for debugging and monitoring.
6
+
7
+ Error Code Format: E-<DOMAIN>-<NUMBER>
8
+ - DOMAIN: 3-letter code identifying the module/domain
9
+ - NUMBER: 3-digit unique identifier
10
+
11
+ Example: E-RET-001 (Retry domain, error #1)
12
+ """
13
+
14
+ from dataclasses import dataclass
15
+ from enum import Enum
16
+ from typing import Dict, Optional
17
+
18
+ from dory.utils.errors import DoryError as _DoryErrorBase
19
+
20
+
21
+ class ErrorDomain(str, Enum):
22
+ """Error domains for categorizing errors."""
23
+
24
+ # Core SDK
25
+ CORE = "COR" # Core SDK functionality
26
+ STATE = "STA" # State management
27
+ MIGRATION = "MIG" # Migration operations
28
+
29
+ # Resilience
30
+ RETRY = "RET" # Retry logic
31
+ CIRCUIT_BREAKER = "CBR" # Circuit breaker
32
+ ERROR_CLASS = "ECL" # Error classification
33
+
34
+ # Recovery
35
+ GOLDEN_IMAGE = "GLD" # Golden image/snapshots
36
+ RECOVERY = "REC" # Recovery operations
37
+ VALIDATION = "VAL" # Validation
38
+
39
+ # Processing
40
+ PROCESSOR = "PRC" # Processor operations
41
+ MODE = "MOD" # Processing modes
42
+ QUEUE = "QUE" # Queue operations
43
+
44
+ # Monitoring
45
+ METRICS = "MET" # Metrics collection
46
+ HEALTH = "HLT" # Health checks
47
+ TELEMETRY = "TEL" # OpenTelemetry
48
+
49
+ # Infrastructure
50
+ KUBERNETES = "K8S" # Kubernetes operations
51
+ STORAGE = "STO" # Storage operations
52
+ NETWORK = "NET" # Network operations
53
+
54
+ # Middleware
55
+ REQUEST = "REQ" # Request tracking
56
+ CONNECTION = "CON" # Connection management
57
+ SESSION = "SES" # Session management
58
+
59
+
60
+ @dataclass(frozen=True)
61
+ class ErrorCode:
62
+ """Represents a structured error code."""
63
+
64
+ domain: ErrorDomain
65
+ number: int
66
+ message: str
67
+ description: str
68
+ remediation: str
69
+ severity: str = "ERROR"
70
+
71
+ @property
72
+ def code(self) -> str:
73
+ """Get formatted error code (e.g., E-RET-001)."""
74
+ return f"E-{self.domain.value}-{self.number:03d}"
75
+
76
+ def __str__(self) -> str:
77
+ """String representation of error code."""
78
+ return f"[{self.code}] {self.message}"
79
+
80
+ def format_full(self) -> str:
81
+ """Get full formatted error message."""
82
+ return f"""
83
+ Error Code: {self.code}
84
+ Severity: {self.severity}
85
+ Message: {self.message}
86
+ Description: {self.description}
87
+ Remediation: {self.remediation}
88
+ """.strip()
89
+
90
+
91
+ # ============================================================================
92
+ # RETRY ERRORS (E-RET-xxx)
93
+ # ============================================================================
94
+
95
+ E_RET_001 = ErrorCode(
96
+ domain=ErrorDomain.RETRY,
97
+ number=1,
98
+ message="Retry budget exhausted",
99
+ description="The retry budget has been depleted. No more retries are allowed.",
100
+ remediation="Wait for budget to replenish or increase max_retry_budget.",
101
+ severity="ERROR",
102
+ )
103
+
104
+ E_RET_002 = ErrorCode(
105
+ domain=ErrorDomain.RETRY,
106
+ number=2,
107
+ message="Max retry attempts exceeded",
108
+ description="Operation failed after maximum retry attempts.",
109
+ remediation="Check operation logic and increase max_attempts if appropriate.",
110
+ severity="ERROR",
111
+ )
112
+
113
+ E_RET_003 = ErrorCode(
114
+ domain=ErrorDomain.RETRY,
115
+ number=3,
116
+ message="Backoff timeout exceeded",
117
+ description="Total backoff time exceeded max_backoff_time.",
118
+ remediation="Increase max_backoff_time or reduce initial_delay/max_delay.",
119
+ severity="ERROR",
120
+ )
121
+
122
+ # ============================================================================
123
+ # CIRCUIT BREAKER ERRORS (E-CBR-xxx)
124
+ # ============================================================================
125
+
126
+ E_CBR_001 = ErrorCode(
127
+ domain=ErrorDomain.CIRCUIT_BREAKER,
128
+ number=1,
129
+ message="Circuit breaker is OPEN",
130
+ description="Circuit breaker is open due to high failure rate. Requests are being rejected.",
131
+ remediation="Wait for circuit breaker to enter HALF_OPEN state or manually reset.",
132
+ severity="WARNING",
133
+ )
134
+
135
+ E_CBR_002 = ErrorCode(
136
+ domain=ErrorDomain.CIRCUIT_BREAKER,
137
+ number=2,
138
+ message="Circuit breaker transition failed",
139
+ description="Failed to transition circuit breaker state.",
140
+ remediation="Check circuit breaker configuration and state consistency.",
141
+ severity="ERROR",
142
+ )
143
+
144
+ E_CBR_003 = ErrorCode(
145
+ domain=ErrorDomain.CIRCUIT_BREAKER,
146
+ number=3,
147
+ message="Failure threshold exceeded",
148
+ description="Operation failures exceeded the circuit breaker threshold.",
149
+ remediation="Investigate underlying failures and adjust failure_threshold if needed.",
150
+ severity="WARNING",
151
+ )
152
+
153
+ # ============================================================================
154
+ # ERROR CLASSIFICATION ERRORS (E-ECL-xxx)
155
+ # ============================================================================
156
+
157
+ E_ECL_001 = ErrorCode(
158
+ domain=ErrorDomain.ERROR_CLASS,
159
+ number=1,
160
+ message="Unable to classify error",
161
+ description="Error classification failed - error type could not be determined.",
162
+ remediation="Add error pattern to classifier or handle as UNKNOWN type.",
163
+ severity="WARNING",
164
+ )
165
+
166
+ E_ECL_002 = ErrorCode(
167
+ domain=ErrorDomain.ERROR_CLASS,
168
+ number=2,
169
+ message="Error classification confidence low",
170
+ description="Error was classified but with low confidence score.",
171
+ remediation="Review error patterns and improve classification rules.",
172
+ severity="INFO",
173
+ )
174
+
175
+ # ============================================================================
176
+ # GOLDEN IMAGE ERRORS (E-GLD-xxx)
177
+ # ============================================================================
178
+
179
+ E_GLD_001 = ErrorCode(
180
+ domain=ErrorDomain.GOLDEN_IMAGE,
181
+ number=1,
182
+ message="Golden snapshot capture failed",
183
+ description="Failed to capture golden state snapshot.",
184
+ remediation="Check storage permissions and available space.",
185
+ severity="ERROR",
186
+ )
187
+
188
+ E_GLD_002 = ErrorCode(
189
+ domain=ErrorDomain.GOLDEN_IMAGE,
190
+ number=2,
191
+ message="Golden snapshot restore failed",
192
+ description="Failed to restore state from golden snapshot.",
193
+ remediation="Verify snapshot integrity and compatibility with current version.",
194
+ severity="ERROR",
195
+ )
196
+
197
+ E_GLD_003 = ErrorCode(
198
+ domain=ErrorDomain.GOLDEN_IMAGE,
199
+ number=3,
200
+ message="Snapshot checksum mismatch",
201
+ description="Snapshot checksum verification failed - data may be corrupted.",
202
+ remediation="Recapture snapshot or restore from backup.",
203
+ severity="CRITICAL",
204
+ )
205
+
206
+ E_GLD_004 = ErrorCode(
207
+ domain=ErrorDomain.GOLDEN_IMAGE,
208
+ number=4,
209
+ message="Snapshot compression failed",
210
+ description="Failed to compress snapshot data.",
211
+ remediation="Check available memory and disk space.",
212
+ severity="ERROR",
213
+ )
214
+
215
+ E_GLD_005 = ErrorCode(
216
+ domain=ErrorDomain.GOLDEN_IMAGE,
217
+ number=5,
218
+ message="Graduated reset failed",
219
+ description="All graduated reset levels failed to restore state.",
220
+ remediation="Manual intervention required - check logs for specific failures.",
221
+ severity="CRITICAL",
222
+ )
223
+
224
+ # ============================================================================
225
+ # VALIDATION ERRORS (E-VAL-xxx)
226
+ # ============================================================================
227
+
228
+ E_VAL_001 = ErrorCode(
229
+ domain=ErrorDomain.VALIDATION,
230
+ number=1,
231
+ message="State validation failed",
232
+ description="State validation found critical issues.",
233
+ remediation="Review validation errors and fix state data.",
234
+ severity="ERROR",
235
+ )
236
+
237
+ E_VAL_002 = ErrorCode(
238
+ domain=ErrorDomain.VALIDATION,
239
+ number=2,
240
+ message="Schema validation failed",
241
+ description="State does not match expected schema.",
242
+ remediation="Update state to match schema or update schema definition.",
243
+ severity="ERROR",
244
+ )
245
+
246
+ E_VAL_003 = ErrorCode(
247
+ domain=ErrorDomain.VALIDATION,
248
+ number=3,
249
+ message="Dependency validation failed",
250
+ description="Required dependencies are missing or invalid.",
251
+ remediation="Ensure all required dependencies are present and valid.",
252
+ severity="ERROR",
253
+ )
254
+
255
+ # ============================================================================
256
+ # PROCESSING MODE ERRORS (E-MOD-xxx)
257
+ # ============================================================================
258
+
259
+ E_MOD_001 = ErrorCode(
260
+ domain=ErrorDomain.MODE,
261
+ number=1,
262
+ message="Mode transition failed",
263
+ description="Failed to transition to target processing mode.",
264
+ remediation="Check mode transition preconditions and system state.",
265
+ severity="ERROR",
266
+ )
267
+
268
+ E_MOD_002 = ErrorCode(
269
+ domain=ErrorDomain.MODE,
270
+ number=2,
271
+ message="Invalid mode for operation",
272
+ description="Operation not available in current processing mode.",
273
+ remediation="Wait for mode transition or use degraded operation variant.",
274
+ severity="WARNING",
275
+ )
276
+
277
+ E_MOD_003 = ErrorCode(
278
+ domain=ErrorDomain.MODE,
279
+ number=3,
280
+ message="Mode auto-recovery failed",
281
+ description="Automatic mode recovery did not succeed.",
282
+ remediation="Manual intervention required to restore normal mode.",
283
+ severity="ERROR",
284
+ )
285
+
286
+ # ============================================================================
287
+ # REQUEST TRACKING ERRORS (E-REQ-xxx)
288
+ # ============================================================================
289
+
290
+ E_REQ_001 = ErrorCode(
291
+ domain=ErrorDomain.REQUEST,
292
+ number=1,
293
+ message="Request tracking initialization failed",
294
+ description="Failed to initialize request tracking.",
295
+ remediation="Check RequestTracker configuration and retry.",
296
+ severity="WARNING",
297
+ )
298
+
299
+ E_REQ_002 = ErrorCode(
300
+ domain=ErrorDomain.REQUEST,
301
+ number=2,
302
+ message="Request timeout exceeded",
303
+ description="Request exceeded configured timeout duration.",
304
+ remediation="Increase timeout or optimize request processing.",
305
+ severity="WARNING",
306
+ )
307
+
308
+ # ============================================================================
309
+ # CONNECTION ERRORS (E-CON-xxx)
310
+ # ============================================================================
311
+
312
+ E_CON_001 = ErrorCode(
313
+ domain=ErrorDomain.CONNECTION,
314
+ number=1,
315
+ message="Connection health check failed",
316
+ description="Connection failed health check.",
317
+ remediation="Verify connection is alive and responsive.",
318
+ severity="WARNING",
319
+ )
320
+
321
+ E_CON_002 = ErrorCode(
322
+ domain=ErrorDomain.CONNECTION,
323
+ number=2,
324
+ message="Connection idle timeout",
325
+ description="Connection closed due to idle timeout.",
326
+ remediation="Increase idle_timeout or ensure connection is actively used.",
327
+ severity="INFO",
328
+ )
329
+
330
+ E_CON_003 = ErrorCode(
331
+ domain=ErrorDomain.CONNECTION,
332
+ number=3,
333
+ message="Connection registration failed",
334
+ description="Failed to register connection with tracker.",
335
+ remediation="Check connection is valid and tracker is initialized.",
336
+ severity="ERROR",
337
+ )
338
+
339
+ # ============================================================================
340
+ # STATE MANAGEMENT ERRORS (E-STA-xxx)
341
+ # ============================================================================
342
+
343
+ E_STA_001 = ErrorCode(
344
+ domain=ErrorDomain.STATE,
345
+ number=1,
346
+ message="State serialization failed",
347
+ description="Failed to serialize state data.",
348
+ remediation="Ensure state contains only serializable types.",
349
+ severity="ERROR",
350
+ )
351
+
352
+ E_STA_002 = ErrorCode(
353
+ domain=ErrorDomain.STATE,
354
+ number=2,
355
+ message="State deserialization failed",
356
+ description="Failed to deserialize state data.",
357
+ remediation="Verify state format and version compatibility.",
358
+ severity="ERROR",
359
+ )
360
+
361
+ E_STA_003 = ErrorCode(
362
+ domain=ErrorDomain.STATE,
363
+ number=3,
364
+ message="State corruption detected",
365
+ description="State data appears to be corrupted.",
366
+ remediation="Restore from golden snapshot or recapture state.",
367
+ severity="CRITICAL",
368
+ )
369
+
370
+ # ============================================================================
371
+ # ERROR CODE REGISTRY
372
+ # ============================================================================
373
+
374
+
375
+ class ErrorCodeRegistry:
376
+ """Registry for all error codes."""
377
+
378
+ _codes: Dict[str, ErrorCode] = {}
379
+
380
+ @classmethod
381
+ def register(cls, error_code: ErrorCode) -> None:
382
+ """Register an error code."""
383
+ cls._codes[error_code.code] = error_code
384
+
385
+ @classmethod
386
+ def get(cls, code: str) -> Optional[ErrorCode]:
387
+ """Get error code by code string."""
388
+ return cls._codes.get(code)
389
+
390
+ @classmethod
391
+ def search(cls, query: str) -> list[ErrorCode]:
392
+ """Search error codes by message or description."""
393
+ query_lower = query.lower()
394
+ return [
395
+ code
396
+ for code in cls._codes.values()
397
+ if query_lower in code.message.lower()
398
+ or query_lower in code.description.lower()
399
+ ]
400
+
401
+ @classmethod
402
+ def list_by_domain(cls, domain: ErrorDomain) -> list[ErrorCode]:
403
+ """List all error codes for a domain."""
404
+ return [code for code in cls._codes.values() if code.domain == domain]
405
+
406
+ @classmethod
407
+ def all(cls) -> list[ErrorCode]:
408
+ """Get all registered error codes."""
409
+ return sorted(cls._codes.values(), key=lambda c: c.code)
410
+
411
+
412
+ # Auto-register all error codes defined in this module
413
+ _error_codes = [
414
+ # Retry
415
+ E_RET_001,
416
+ E_RET_002,
417
+ E_RET_003,
418
+ # Circuit Breaker
419
+ E_CBR_001,
420
+ E_CBR_002,
421
+ E_CBR_003,
422
+ # Error Classification
423
+ E_ECL_001,
424
+ E_ECL_002,
425
+ # Golden Image
426
+ E_GLD_001,
427
+ E_GLD_002,
428
+ E_GLD_003,
429
+ E_GLD_004,
430
+ E_GLD_005,
431
+ # Validation
432
+ E_VAL_001,
433
+ E_VAL_002,
434
+ E_VAL_003,
435
+ # Processing Mode
436
+ E_MOD_001,
437
+ E_MOD_002,
438
+ E_MOD_003,
439
+ # Request Tracking
440
+ E_REQ_001,
441
+ E_REQ_002,
442
+ # Connection
443
+ E_CON_001,
444
+ E_CON_002,
445
+ E_CON_003,
446
+ # State Management
447
+ E_STA_001,
448
+ E_STA_002,
449
+ E_STA_003,
450
+ ]
451
+
452
+ for _code in _error_codes:
453
+ ErrorCodeRegistry.register(_code)
454
+
455
+
456
+ # ============================================================================
457
+ # ERROR CODE EXCEPTIONS
458
+ # ============================================================================
459
+
460
+
461
+ class DoryError(_DoryErrorBase):
462
+ """Exception with structured error code support.
463
+
464
+ Inherits from dory.utils.errors.DoryError so catching the base
465
+ DoryError will also catch coded errors.
466
+ """
467
+
468
+ def __init__(
469
+ self,
470
+ error_code: ErrorCode,
471
+ details: Optional[str] = None,
472
+ cause: Optional[Exception] = None,
473
+ ):
474
+ """
475
+ Initialize error with code.
476
+
477
+ Args:
478
+ error_code: The error code
479
+ details: Additional context-specific details
480
+ cause: Original exception that caused this error
481
+ """
482
+ self.error_code = error_code
483
+ self.details = details
484
+
485
+ message = str(error_code)
486
+ if details:
487
+ message += f"\nDetails: {details}"
488
+
489
+ super().__init__(message, cause=cause)
490
+
491
+ def format_full(self) -> str:
492
+ """Get full formatted error message."""
493
+ msg = self.error_code.format_full()
494
+ if self.details:
495
+ msg += f"\n\nAdditional Details:\n{self.details}"
496
+ if self.cause:
497
+ msg += f"\n\nCaused by:\n{self.cause}"
498
+ return msg
dory/geo/__init__.py ADDED
@@ -0,0 +1,40 @@
1
+ """
2
+ Geolocation estimation from camera detections.
3
+
4
+ Converts detected object positions in camera images to geographic
5
+ coordinates (lat/lng) using one of two strategies:
6
+
7
+ **Homography** (default) — best for flat ground planes::
8
+
9
+ from dory.geo import CameraGeolocalizer, ReferencePoint, BoundingBox
10
+
11
+ geo = CameraGeolocalizer(refs)
12
+ loc = geo.estimate(BoundingBox(left=250, top=100, width=80, height=200))
13
+
14
+ **Trilateration + linear interpolation** — best for scattered points::
15
+
16
+ from dory.geo import CameraGeolocalizer, GeoMethod
17
+
18
+ geo = CameraGeolocalizer(refs, method=GeoMethod.TRILATERATION)
19
+ loc = geo.estimate(box)
20
+ """
21
+
22
+ from dory.geo.geolocalizer import (
23
+ BoundingBox,
24
+ CameraGeolocalizer,
25
+ GeoMethod,
26
+ GeoPoint,
27
+ ReferencePoint,
28
+ estimate_location,
29
+ estimate_locations_batch,
30
+ )
31
+
32
+ __all__ = [
33
+ "BoundingBox",
34
+ "CameraGeolocalizer",
35
+ "GeoMethod",
36
+ "GeoPoint",
37
+ "ReferencePoint",
38
+ "estimate_location",
39
+ "estimate_locations_batch",
40
+ ]