async-durable-execution-runner 2.0.0a1__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 (55) hide show
  1. LICENSE +175 -0
  2. NOTICE +8 -0
  3. VERSION.py +5 -0
  4. async_durable_execution_runner/__about__.py +33 -0
  5. async_durable_execution_runner/__init__.py +23 -0
  6. async_durable_execution_runner/checkpoint/__init__.py +1 -0
  7. async_durable_execution_runner/checkpoint/processor.py +101 -0
  8. async_durable_execution_runner/checkpoint/processors/__init__.py +1 -0
  9. async_durable_execution_runner/checkpoint/processors/base.py +199 -0
  10. async_durable_execution_runner/checkpoint/processors/callback.py +89 -0
  11. async_durable_execution_runner/checkpoint/processors/context.py +59 -0
  12. async_durable_execution_runner/checkpoint/processors/execution.py +52 -0
  13. async_durable_execution_runner/checkpoint/processors/step.py +124 -0
  14. async_durable_execution_runner/checkpoint/processors/wait.py +95 -0
  15. async_durable_execution_runner/checkpoint/transformer.py +104 -0
  16. async_durable_execution_runner/checkpoint/validators/__init__.py +1 -0
  17. async_durable_execution_runner/checkpoint/validators/checkpoint.py +242 -0
  18. async_durable_execution_runner/checkpoint/validators/operations/__init__.py +1 -0
  19. async_durable_execution_runner/checkpoint/validators/operations/callback.py +45 -0
  20. async_durable_execution_runner/checkpoint/validators/operations/context.py +73 -0
  21. async_durable_execution_runner/checkpoint/validators/operations/execution.py +47 -0
  22. async_durable_execution_runner/checkpoint/validators/operations/invoke.py +56 -0
  23. async_durable_execution_runner/checkpoint/validators/operations/step.py +106 -0
  24. async_durable_execution_runner/checkpoint/validators/operations/wait.py +54 -0
  25. async_durable_execution_runner/checkpoint/validators/transitions.py +66 -0
  26. async_durable_execution_runner/cli.py +498 -0
  27. async_durable_execution_runner/client.py +50 -0
  28. async_durable_execution_runner/exceptions.py +288 -0
  29. async_durable_execution_runner/execution.py +444 -0
  30. async_durable_execution_runner/executor.py +1234 -0
  31. async_durable_execution_runner/invoker.py +340 -0
  32. async_durable_execution_runner/model.py +3296 -0
  33. async_durable_execution_runner/observer.py +144 -0
  34. async_durable_execution_runner/py.typed +1 -0
  35. async_durable_execution_runner/runner.py +1167 -0
  36. async_durable_execution_runner/scheduler.py +246 -0
  37. async_durable_execution_runner/stores/__init__.py +1 -0
  38. async_durable_execution_runner/stores/base.py +147 -0
  39. async_durable_execution_runner/stores/filesystem.py +79 -0
  40. async_durable_execution_runner/stores/memory.py +38 -0
  41. async_durable_execution_runner/stores/sqlite.py +273 -0
  42. async_durable_execution_runner/token.py +49 -0
  43. async_durable_execution_runner/web/__init__.py +1 -0
  44. async_durable_execution_runner/web/errors.py +8 -0
  45. async_durable_execution_runner/web/handlers.py +813 -0
  46. async_durable_execution_runner/web/models.py +266 -0
  47. async_durable_execution_runner/web/routes.py +692 -0
  48. async_durable_execution_runner/web/serialization.py +235 -0
  49. async_durable_execution_runner/web/server.py +243 -0
  50. async_durable_execution_runner-2.0.0a1.dist-info/METADATA +238 -0
  51. async_durable_execution_runner-2.0.0a1.dist-info/RECORD +55 -0
  52. async_durable_execution_runner-2.0.0a1.dist-info/WHEEL +4 -0
  53. async_durable_execution_runner-2.0.0a1.dist-info/entry_points.txt +2 -0
  54. async_durable_execution_runner-2.0.0a1.dist-info/licenses/LICENSE +175 -0
  55. async_durable_execution_runner-2.0.0a1.dist-info/licenses/NOTICE +1 -0
@@ -0,0 +1,288 @@
1
+ """Exceptions for the Durable Executions Testing Library.
2
+
3
+ This module provides AWS-compliant exceptions that serialize to the exact JSON format
4
+ expected by boto3 and AWS services. All exceptions follow Smithy model definitions
5
+ for field names and structure.
6
+
7
+ ## AWS-Compliant Error Format
8
+
9
+ All AWS API exceptions inherit from `AwsApiException` and implement the `to_dict()` method
10
+ to serialize to AWS-compliant JSON format. The format varies by exception type based on
11
+ their Smithy model definitions:
12
+
13
+ ### Standard Format (most exceptions):
14
+ ```json
15
+ {
16
+ "Type": "ExceptionName",
17
+ "message": "Error message" // or "Message" depending on Smithy definition
18
+ }
19
+ ```
20
+
21
+ ### Special Cases:
22
+ - `ExecutionAlreadyStartedException`: No "Type" field, includes "DurableExecutionArn"
23
+ ```json
24
+ {
25
+ "message": "Error message",
26
+ "DurableExecutionArn": "arn:aws:states:..."
27
+ }
28
+ ```
29
+
30
+ ## Field Name Conventions
31
+
32
+ Field names follow the exact Smithy model definitions:
33
+ - `InvalidParameterValueException`: uses lowercase "message"
34
+ - `CallbackTimeoutException`: uses lowercase "message"
35
+ - `ResourceNotFoundException`: uses capital "Message"
36
+ - `ServiceException`: uses capital "Message"
37
+ - `ExecutionAlreadyStartedException`: uses lowercase "message" + "DurableExecutionArn"
38
+
39
+ ## HTTP Status Codes
40
+
41
+ Each exception maps to appropriate HTTP status codes:
42
+ - 400: InvalidParameterValueException (Bad Request)
43
+ - 404: ResourceNotFoundException (Not Found)
44
+ - 408: CallbackTimeoutException (Request Timeout)
45
+ - 409: ExecutionAlreadyStartedException (Conflict)
46
+ - 500: ServiceException (Internal Server Error)
47
+
48
+ ## Usage Examples
49
+
50
+ ```python
51
+ # Create and serialize an exception
52
+ exception = InvalidParameterValueException("Invalid parameter value")
53
+ json_dict = exception.to_dict()
54
+ # Result: {"Type": "InvalidParameterValueException", "message": "Invalid parameter value"}
55
+
56
+ # HTTP response creation
57
+ from async_durable_execution_runner.web.models import HTTPResponse
58
+
59
+ response = HTTPResponse.create_error_from_exception(exception)
60
+ # Creates HTTP 400 response with AWS-compliant JSON body
61
+ ```
62
+
63
+ ## Boto3 Compatibility
64
+
65
+ All exceptions are designed to be compatible with boto3's error handling:
66
+ - JSON structure matches boto3 expectations
67
+ - Field names match Smithy model definitions
68
+ - Type field values match exception class names
69
+ - Can be deserialized by boto3's error factory
70
+
71
+ Avoid any non-stdlib references in this module, it is at the bottom of the dependency chain.
72
+ """
73
+
74
+ from __future__ import annotations
75
+
76
+ from typing import Any
77
+
78
+
79
+ # region Local Runner
80
+ class DurableFunctionsLocalRunnerError(Exception):
81
+ """Base class for Durable Executions exceptions"""
82
+
83
+
84
+ class UnknownRouteError(DurableFunctionsLocalRunnerError):
85
+ """No route matches the requested path pattern."""
86
+
87
+ def __init__(self, method: str, path: str) -> None:
88
+ """Initialize UnknownRouteError with method and path.
89
+
90
+ Args:
91
+ method: HTTP method (GET, POST, etc.)
92
+ path: Request path that couldn't be matched
93
+ """
94
+ self.method = method
95
+ self.path = path
96
+ message = f"Unknown path pattern: {method} {path}"
97
+ super().__init__(message)
98
+
99
+
100
+ # endregion Local Runner
101
+
102
+
103
+ class SerializationError(DurableFunctionsLocalRunnerError):
104
+ """Exception for serialization errors."""
105
+
106
+
107
+ # region Testing
108
+ class DurableFunctionsTestError(Exception):
109
+ """Base class for testing errors."""
110
+
111
+
112
+ # endregion Testing
113
+
114
+
115
+ # region AWS API Exceptions
116
+ class AwsApiException(DurableFunctionsLocalRunnerError): # noqa: N818
117
+ """Base class for AWS API-style exceptions that can be serialized to AWS format."""
118
+
119
+ http_status_code: int = 500 # Default to server error
120
+
121
+ def to_dict(self) -> dict[str, Any]:
122
+ """Serialize to AWS-compliant JSON structure."""
123
+ raise NotImplementedError
124
+
125
+
126
+ # Smithy-Mapped Exceptions (defined in Smithy models)
127
+ class InvalidParameterValueException(AwsApiException):
128
+ """Exception for invalid parameter values."""
129
+
130
+ http_status_code = 400
131
+
132
+ def __init__(self, message: str) -> None:
133
+ """Initialize with message field (lowercase per Smithy definition)."""
134
+ self.message = message
135
+ super().__init__(message)
136
+
137
+ def to_dict(self) -> dict[str, Any]:
138
+ """Serialize to AWS-compliant JSON structure."""
139
+ return {"Type": "InvalidParameterValueException", "message": self.message}
140
+
141
+
142
+ class ResourceNotFoundException(AwsApiException):
143
+ """Exception for resource not found errors."""
144
+
145
+ http_status_code = 404
146
+
147
+ def __init__(
148
+ self,
149
+ Message: str, # noqa: N803
150
+ ) -> None: # Capital M per Smithy definition
151
+ """Initialize with Message field (capital M per Smithy definition)."""
152
+ self.Message = Message
153
+ super().__init__(Message)
154
+
155
+ def to_dict(self) -> dict[str, Any]:
156
+ """Serialize to AWS-compliant JSON structure."""
157
+ return {"Type": "ResourceNotFoundException", "Message": self.Message}
158
+
159
+
160
+ class ServiceException(AwsApiException):
161
+ """Exception for general service errors."""
162
+
163
+ http_status_code = 500
164
+
165
+ def __init__(
166
+ self,
167
+ Message: str, # noqa: N803
168
+ ) -> None: # Capital M per Smithy definition
169
+ """Initialize with Message field (capital M per Smithy definition)."""
170
+ self.Message = Message
171
+ super().__init__(Message)
172
+
173
+ def to_dict(self) -> dict[str, Any]:
174
+ """Serialize to AWS-compliant JSON structure."""
175
+ return {"Type": "ServiceException", "Message": self.Message}
176
+
177
+
178
+ class ExecutionAlreadyStartedException(AwsApiException):
179
+ """Exception for execution already started errors."""
180
+
181
+ http_status_code = 409
182
+
183
+ def __init__(self, message: str, DurableExecutionArn: str) -> None: # noqa: N803
184
+ """Initialize with message and DurableExecutionArn fields."""
185
+ self.message = message
186
+ self.DurableExecutionArn = DurableExecutionArn
187
+ super().__init__(message)
188
+
189
+ def to_dict(self) -> dict[str, Any]:
190
+ """Serialize to AWS-compliant JSON structure (no Type field per Smithy definition)."""
191
+ return {
192
+ "message": self.message,
193
+ "DurableExecutionArn": self.DurableExecutionArn,
194
+ }
195
+
196
+
197
+ class ExecutionConflictException(AwsApiException):
198
+ """Exception for execution conflict errors."""
199
+
200
+ http_status_code = 409
201
+
202
+ def __init__(self, message: str) -> None:
203
+ """Initialize with message field."""
204
+ self.message = message
205
+ super().__init__(message)
206
+
207
+ def to_dict(self) -> dict[str, Any]:
208
+ """Serialize to AWS-compliant JSON structure."""
209
+ return {"Type": "ExecutionConflictException", "message": self.message}
210
+
211
+
212
+ class CallbackTimeoutException(AwsApiException):
213
+ """Exception for callback timeout errors."""
214
+
215
+ http_status_code = 408
216
+
217
+ def __init__(self, message: str) -> None:
218
+ """Initialize with message field (lowercase per Smithy definition)."""
219
+ self.message = message
220
+ super().__init__(message)
221
+
222
+ def to_dict(self) -> dict[str, Any]:
223
+ """Serialize to AWS-compliant JSON structure."""
224
+ return {"Type": "CallbackTimeoutException", "message": self.message}
225
+
226
+
227
+ class TooManyRequestsException(AwsApiException):
228
+ """Exception for too many requests errors."""
229
+
230
+ http_status_code = 429
231
+
232
+ def __init__(self, message: str) -> None:
233
+ """Initialize with message field (lowercase per Smithy definition)."""
234
+ self.message = message
235
+ super().__init__(message)
236
+
237
+ def to_dict(self) -> dict[str, Any]:
238
+ """Serialize to AWS-compliant JSON structure."""
239
+ return {"Type": "TooManyRequestsException", "message": self.message}
240
+
241
+
242
+ # Unmapped Exceptions (thrown by services but not in Smithy)
243
+ class IllegalStateException(AwsApiException):
244
+ """IllegalStateException."""
245
+
246
+ http_status_code = 500
247
+
248
+ def __init__(self, message: str) -> None:
249
+ """Initialize with message field."""
250
+ self.message = message
251
+ super().__init__(message)
252
+
253
+ def to_dict(self) -> dict[str, Any]:
254
+ """Serialize to AWS-compliant JSON structure (maps to ServiceException)."""
255
+ return {"Type": "ServiceException", "Message": self.message}
256
+
257
+
258
+ class RuntimeException(AwsApiException):
259
+ """RuntimeException."""
260
+
261
+ http_status_code = 500
262
+
263
+ def __init__(self, message: str) -> None:
264
+ """Initialize with message field."""
265
+ self.message = message
266
+ super().__init__(message)
267
+
268
+ def to_dict(self) -> dict[str, Any]:
269
+ """Serialize to AWS-compliant JSON structure (maps to ServiceException)."""
270
+ return {"Type": "ServiceException", "Message": self.message}
271
+
272
+
273
+ class IllegalArgumentException(AwsApiException):
274
+ """IllegalArgumentException."""
275
+
276
+ http_status_code = 400
277
+
278
+ def __init__(self, message: str) -> None:
279
+ """Initialize with message field."""
280
+ self.message = message
281
+ super().__init__(message)
282
+
283
+ def to_dict(self) -> dict[str, Any]:
284
+ """Serialize to AWS-compliant JSON structure (maps to InvalidParameterValueException)."""
285
+ return {"Type": "InvalidParameterValueException", "message": self.message}
286
+
287
+
288
+ # endregion AWS API Exceptions