async-durable-execution-runner 2.0.0a1__tar.gz → 2.0.0a2__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.
Files changed (53) hide show
  1. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/.gitignore +1 -1
  2. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/PKG-INFO +30 -22
  3. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/README.md +26 -19
  4. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/VERSION.py +1 -1
  5. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/__init__.py +10 -7
  6. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/processor.py +9 -10
  7. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/processors/base.py +5 -5
  8. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/processors/callback.py +11 -10
  9. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/processors/context.py +4 -5
  10. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/processors/execution.py +5 -10
  11. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/processors/step.py +11 -8
  12. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/processors/wait.py +7 -8
  13. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/transformer.py +9 -10
  14. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/checkpoint.py +10 -11
  15. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/operations/callback.py +2 -3
  16. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/operations/context.py +2 -3
  17. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/operations/execution.py +2 -3
  18. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/operations/invoke.py +2 -3
  19. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/operations/step.py +2 -3
  20. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/operations/wait.py +2 -3
  21. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/transitions.py +8 -9
  22. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/cli.py +25 -22
  23. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/client.py +6 -7
  24. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/exceptions.py +1 -13
  25. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/execution.py +12 -15
  26. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/executor.py +67 -42
  27. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/invoker.py +21 -12
  28. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/model.py +13 -70
  29. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/observer.py +4 -6
  30. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/runner.py +259 -140
  31. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/scheduler.py +35 -24
  32. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/stores/base.py +5 -6
  33. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/stores/filesystem.py +3 -3
  34. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/stores/memory.py +2 -2
  35. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/stores/sqlite.py +5 -5
  36. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/web/handlers.py +15 -17
  37. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/web/models.py +3 -3
  38. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/web/routes.py +1 -1
  39. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/web/serialization.py +4 -6
  40. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/web/server.py +10 -10
  41. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/pyproject.toml +18 -19
  42. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/LICENSE +0 -0
  43. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/NOTICE +0 -0
  44. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/__about__.py +0 -0
  45. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/__init__.py +0 -0
  46. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/processors/__init__.py +0 -0
  47. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/__init__.py +0 -0
  48. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/checkpoint/validators/operations/__init__.py +0 -0
  49. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/py.typed +0 -0
  50. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/stores/__init__.py +0 -0
  51. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/token.py +0 -0
  52. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/web/__init__.py +0 -0
  53. {async_durable_execution_runner-2.0.0a1 → async_durable_execution_runner-2.0.0a2}/async_durable_execution_runner/web/errors.py +0 -0
@@ -21,7 +21,7 @@ __pycache__/
21
21
  /build
22
22
 
23
23
  .venv
24
- .venv/
24
+ .venv*/
25
25
 
26
26
  .attach_*
27
27
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: async-durable-execution-runner
3
- Version: 2.0.0a1
3
+ Version: 2.0.0a2
4
4
  Summary: Community-maintained durable execution local and cloud test runner for Python
5
5
  Project-URL: Documentation, https://github.com/zhongkechen/async-durable-execution#readme
6
6
  Project-URL: Issues, https://github.com/zhongkechen/async-durable-execution/issues
@@ -11,17 +11,20 @@ License-File: LICENSE
11
11
  License-File: NOTICE
12
12
  Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3.10
14
15
  Classifier: Programming Language :: Python :: 3.11
15
16
  Classifier: Programming Language :: Python :: 3.12
16
17
  Classifier: Programming Language :: Python :: 3.13
17
18
  Classifier: Programming Language :: Python :: 3.14
18
19
  Classifier: Programming Language :: Python :: Implementation :: CPython
19
20
  Classifier: Programming Language :: Python :: Implementation :: PyPy
20
- Requires-Python: >=3.11
21
- Requires-Dist: async-durable-execution>=1.0.0
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: async-durable-execution>=2.0.0a2
22
23
  Requires-Dist: boto3>=1.42.1
23
24
  Description-Content-Type: text/markdown
24
25
 
26
+ from async_durable_execution.operation import child
27
+
25
28
  # Async Durable Execution Runner for Python
26
29
 
27
30
  [![PyPI - Version](https://img.shields.io/pypi/v/async-durable-execution-runner.svg)](https://pypi.org/project/async-durable-execution-runner)
@@ -43,6 +46,8 @@ Description-Content-Type: text/markdown
43
46
 
44
47
  ## Installation
45
48
 
49
+ Requires Python 3.10 or newer.
50
+
46
51
  ```console
47
52
  pip install async-durable-execution-runner
48
53
  ```
@@ -62,58 +67,54 @@ before you deploy it.
62
67
 
63
68
  ```python
64
69
  import asyncio
70
+ from datetime import timedelta
71
+ from functools import partial
65
72
  from typing import Any
66
73
 
67
74
  from async_durable_execution import (
68
- DurableContext,
69
75
  durable_execution,
70
- durable_step,
71
- durable_with_child_context,
76
+ get_current_context,
72
77
  )
73
- from async_durable_execution.config import Duration
74
78
 
75
79
 
76
- @durable_step
77
80
  async def one(a: int, b: int) -> str:
78
81
  await asyncio.sleep(0)
79
82
  return f"{a} {b}"
80
83
 
81
84
 
82
- @durable_step
83
85
  async def two_1(a: int, b: int) -> str:
84
86
  await asyncio.sleep(0)
85
87
  return f"{a} {b}"
86
88
 
87
89
 
88
- @durable_step
89
90
  async def two_2(a: int, b: int) -> str:
90
91
  await asyncio.sleep(0)
91
92
  return f"{b} {a}"
92
93
 
93
94
 
94
- @durable_with_child_context
95
- async def two(ctx: DurableContext, a: int, b: int) -> str:
95
+ async def two(a: int, b: int) -> str:
96
+ ctx = get_current_context()
96
97
  two_1_result: str = ctx.step(two_1(a, b))
97
98
  two_2_result: str = ctx.step(two_2(a, b))
98
99
  return f"{two_1_result} {two_2_result}"
99
100
 
100
101
 
101
- @durable_step
102
102
  async def three(a: int, b: int) -> str:
103
103
  await asyncio.sleep(0)
104
104
  return f"{a} {b}"
105
105
 
106
106
 
107
107
  @durable_execution
108
- async def function_under_test(event: Any, context: DurableContext) -> list[str]:
108
+ async def function_under_test(event: Any) -> list[str]:
109
+ context = get_current_context()
109
110
  results: list[str] = []
110
111
 
111
112
  result_one: str = context.step(one(1, 2))
112
113
  results.append(result_one)
113
114
 
114
- context.wait(duration=Duration.from_seconds(1))
115
+ context.wait(duration=timedelta(seconds=1))
115
116
 
116
- result_two: str = context.run_in_child_context(two(3, 4))
117
+ result_two: str = child.run_in_child_context(partial(two, 3, 4), name="two")
117
118
  results.append(result_two)
118
119
 
119
120
  result_three: str = context.step(three(5, 6))
@@ -125,18 +126,25 @@ async def function_under_test(event: Any, context: DurableContext) -> list[str]:
125
126
  ### Your test code
126
127
 
127
128
  ```python
128
- from async_durable_execution.execution import InvocationStatus
129
- from async_durable_execution_runner.runner import (
129
+ import asyncio
130
+
131
+ from async_durable_execution import InvocationStatus
132
+ from async_durable_execution_runner import (
130
133
  ContextOperation,
134
+ create_runner,
131
135
  DurableFunctionTestResult,
132
- DurableFunctionTestRunner,
133
136
  StepOperation,
134
137
  )
135
138
 
136
139
 
137
140
  def test_my_durable_functions():
138
- with DurableFunctionTestRunner(handler=function_under_test) as runner:
139
- result: DurableFunctionTestResult = runner.run(input="input str", timeout=10)
141
+ with create_runner(
142
+ mode="local",
143
+ handler=function_under_test,
144
+ input="input str",
145
+ timeout=10,
146
+ ) as runner:
147
+ result: DurableFunctionTestResult = asyncio.run(runner.run())
140
148
 
141
149
  assert result.status is InvocationStatus.SUCCEEDED
142
150
  assert result.result == '["1 2", "3 4 4 3", "5 6"]'
@@ -163,7 +171,7 @@ def test_my_durable_functions():
163
171
  5. **ExecutionNotifier** broadcasts events to **Executor** (observer)
164
172
  6. **Executor** updates **Execution** state based on events
165
173
  7. **Execution** completion triggers final event notifications
166
- 8. **DurableTestRunner** run() blocks until it receives completion event, and then returns `DurableFunctionTestResult`.
174
+ 8. **DurableTestRunner** exposes async runner methods, so `await runner.run()` resolves once the execution completes and returns `DurableFunctionTestResult`.
167
175
 
168
176
  ## Major Components
169
177
 
@@ -1,3 +1,5 @@
1
+ from async_durable_execution.operation import child
2
+
1
3
  # Async Durable Execution Runner for Python
2
4
 
3
5
  [![PyPI - Version](https://img.shields.io/pypi/v/async-durable-execution-runner.svg)](https://pypi.org/project/async-durable-execution-runner)
@@ -19,6 +21,8 @@
19
21
 
20
22
  ## Installation
21
23
 
24
+ Requires Python 3.10 or newer.
25
+
22
26
  ```console
23
27
  pip install async-durable-execution-runner
24
28
  ```
@@ -38,58 +42,54 @@ before you deploy it.
38
42
 
39
43
  ```python
40
44
  import asyncio
45
+ from datetime import timedelta
46
+ from functools import partial
41
47
  from typing import Any
42
48
 
43
49
  from async_durable_execution import (
44
- DurableContext,
45
50
  durable_execution,
46
- durable_step,
47
- durable_with_child_context,
51
+ get_current_context,
48
52
  )
49
- from async_durable_execution.config import Duration
50
53
 
51
54
 
52
- @durable_step
53
55
  async def one(a: int, b: int) -> str:
54
56
  await asyncio.sleep(0)
55
57
  return f"{a} {b}"
56
58
 
57
59
 
58
- @durable_step
59
60
  async def two_1(a: int, b: int) -> str:
60
61
  await asyncio.sleep(0)
61
62
  return f"{a} {b}"
62
63
 
63
64
 
64
- @durable_step
65
65
  async def two_2(a: int, b: int) -> str:
66
66
  await asyncio.sleep(0)
67
67
  return f"{b} {a}"
68
68
 
69
69
 
70
- @durable_with_child_context
71
- async def two(ctx: DurableContext, a: int, b: int) -> str:
70
+ async def two(a: int, b: int) -> str:
71
+ ctx = get_current_context()
72
72
  two_1_result: str = ctx.step(two_1(a, b))
73
73
  two_2_result: str = ctx.step(two_2(a, b))
74
74
  return f"{two_1_result} {two_2_result}"
75
75
 
76
76
 
77
- @durable_step
78
77
  async def three(a: int, b: int) -> str:
79
78
  await asyncio.sleep(0)
80
79
  return f"{a} {b}"
81
80
 
82
81
 
83
82
  @durable_execution
84
- async def function_under_test(event: Any, context: DurableContext) -> list[str]:
83
+ async def function_under_test(event: Any) -> list[str]:
84
+ context = get_current_context()
85
85
  results: list[str] = []
86
86
 
87
87
  result_one: str = context.step(one(1, 2))
88
88
  results.append(result_one)
89
89
 
90
- context.wait(duration=Duration.from_seconds(1))
90
+ context.wait(duration=timedelta(seconds=1))
91
91
 
92
- result_two: str = context.run_in_child_context(two(3, 4))
92
+ result_two: str = child.run_in_child_context(partial(two, 3, 4), name="two")
93
93
  results.append(result_two)
94
94
 
95
95
  result_three: str = context.step(three(5, 6))
@@ -101,18 +101,25 @@ async def function_under_test(event: Any, context: DurableContext) -> list[str]:
101
101
  ### Your test code
102
102
 
103
103
  ```python
104
- from async_durable_execution.execution import InvocationStatus
105
- from async_durable_execution_runner.runner import (
104
+ import asyncio
105
+
106
+ from async_durable_execution import InvocationStatus
107
+ from async_durable_execution_runner import (
106
108
  ContextOperation,
109
+ create_runner,
107
110
  DurableFunctionTestResult,
108
- DurableFunctionTestRunner,
109
111
  StepOperation,
110
112
  )
111
113
 
112
114
 
113
115
  def test_my_durable_functions():
114
- with DurableFunctionTestRunner(handler=function_under_test) as runner:
115
- result: DurableFunctionTestResult = runner.run(input="input str", timeout=10)
116
+ with create_runner(
117
+ mode="local",
118
+ handler=function_under_test,
119
+ input="input str",
120
+ timeout=10,
121
+ ) as runner:
122
+ result: DurableFunctionTestResult = asyncio.run(runner.run())
116
123
 
117
124
  assert result.status is InvocationStatus.SUCCEEDED
118
125
  assert result.result == '["1 2", "3 4 4 3", "5 6"]'
@@ -139,7 +146,7 @@ def test_my_durable_functions():
139
146
  5. **ExecutionNotifier** broadcasts events to **Executor** (observer)
140
147
  6. **Executor** updates **Execution** state based on events
141
148
  7. **Execution** completion triggers final event notifications
142
- 8. **DurableTestRunner** run() blocks until it receives completion event, and then returns `DurableFunctionTestResult`.
149
+ 8. **DurableTestRunner** exposes async runner methods, so `await runner.run()` resolves once the execution completes and returns `DurableFunctionTestResult`.
143
150
 
144
151
  ## Major Components
145
152
 
@@ -2,4 +2,4 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  # Modified for the async-durable-execution fork; shared version source for all packages.
5
- __version__ = "2.0.0a1"
5
+ __version__ = "2.0.0a2"
@@ -1,23 +1,26 @@
1
1
  """DurableExecutionsPythonTestingLibrary module."""
2
2
 
3
- from async_durable_execution_runner.runner import (
4
- DurableChildContextTestRunner,
3
+ from .__about__ import __version__
4
+ from .runner import (
5
5
  DurableFunctionCloudTestRunner,
6
+ DurableFunctionLocalTestRunner,
6
7
  DurableFunctionTestResult,
7
- DurableFunctionTestRunner,
8
8
  WebRunner,
9
9
  WebRunnerConfig,
10
+ create_runner,
11
+ ContextOperation,
12
+ StepOperation,
10
13
  )
11
14
 
12
- from async_durable_execution_runner.__about__ import __version__
13
-
14
15
 
15
16
  __all__ = [
16
- "DurableChildContextTestRunner",
17
17
  "DurableFunctionCloudTestRunner",
18
+ "DurableFunctionLocalTestRunner",
18
19
  "DurableFunctionTestResult",
19
- "DurableFunctionTestRunner",
20
20
  "WebRunner",
21
21
  "WebRunnerConfig",
22
22
  "__version__",
23
+ "create_runner",
24
+ "ContextOperation",
25
+ "StepOperation",
23
26
  ]
@@ -4,30 +4,29 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- from async_durable_execution.lambda_service import (
7
+ from async_durable_execution.models import (
8
8
  CheckpointOutput,
9
9
  CheckpointUpdatedExecutionState,
10
10
  OperationUpdate,
11
11
  StateOutput,
12
12
  )
13
-
14
- from async_durable_execution_runner.checkpoint.transformer import (
13
+ from .transformer import (
15
14
  OperationTransformer,
16
15
  )
17
- from async_durable_execution_runner.checkpoint.validators.checkpoint import (
16
+ from .validators.checkpoint import (
18
17
  CheckpointValidator,
19
18
  )
20
- from async_durable_execution_runner.exceptions import (
19
+ from ..exceptions import (
21
20
  InvalidParameterValueException,
22
21
  )
23
- from async_durable_execution_runner.observer import ExecutionNotifier
24
- from async_durable_execution_runner.token import CheckpointToken
22
+ from ..observer import ExecutionNotifier
23
+ from ..token import CheckpointToken
25
24
 
26
25
 
27
26
  if TYPE_CHECKING:
28
- from async_durable_execution_runner.execution import Execution
29
- from async_durable_execution_runner.scheduler import Scheduler
30
- from async_durable_execution_runner.stores.base import ExecutionStore
27
+ from ..execution import Execution
28
+ from ..scheduler import Scheduler
29
+ from ..stores.base import ExecutionStore
31
30
 
32
31
 
33
32
  class CheckpointProcessor:
@@ -6,7 +6,7 @@ import datetime
6
6
  from datetime import timedelta
7
7
  from typing import TYPE_CHECKING
8
8
 
9
- from async_durable_execution.lambda_service import (
9
+ from async_durable_execution.models import (
10
10
  CallbackDetails,
11
11
  ChainedInvokeDetails,
12
12
  ContextDetails,
@@ -22,7 +22,7 @@ from async_durable_execution.lambda_service import (
22
22
 
23
23
 
24
24
  if TYPE_CHECKING:
25
- from async_durable_execution_runner.observer import ExecutionNotifier
25
+ from ...observer import ExecutionNotifier
26
26
 
27
27
 
28
28
  class OperationProcessor:
@@ -44,7 +44,7 @@ class OperationProcessor:
44
44
  start_time: datetime.datetime | None = (
45
45
  current_operation.start_timestamp
46
46
  if current_operation
47
- else datetime.datetime.now(tz=datetime.UTC)
47
+ else datetime.datetime.now(tz=datetime.timezone.utc)
48
48
  )
49
49
  return start_time
50
50
 
@@ -61,7 +61,7 @@ class OperationProcessor:
61
61
  OperationStatus.TIMED_OUT,
62
62
  OperationStatus.STOPPED,
63
63
  }:
64
- return datetime.datetime.now(tz=datetime.UTC)
64
+ return datetime.datetime.now(tz=datetime.timezone.utc)
65
65
  return None
66
66
 
67
67
  def _create_execution_details(
@@ -193,7 +193,7 @@ class OperationProcessor:
193
193
  )
194
194
  else:
195
195
  scheduled_end_timestamp = datetime.datetime.now(
196
- tz=datetime.UTC
196
+ tz=datetime.timezone.utc
197
197
  ) + timedelta(seconds=update.wait_options.wait_seconds)
198
198
  return WaitDetails(scheduled_end_timestamp=scheduled_end_timestamp)
199
199
  return None
@@ -5,25 +5,26 @@ from __future__ import annotations
5
5
  import datetime
6
6
  from typing import TYPE_CHECKING
7
7
 
8
- from async_durable_execution.lambda_service import (
8
+ from async_durable_execution.models import (
9
+ CallbackDetails,
10
+ CallbackOptions,
9
11
  Operation,
10
12
  OperationAction,
11
13
  OperationStatus,
12
- OperationUpdate,
13
- CallbackDetails,
14
14
  OperationType,
15
- CallbackOptions,
15
+ OperationUpdate,
16
16
  )
17
- from async_durable_execution_runner.checkpoint.processors.base import (
17
+ from .base import (
18
18
  OperationProcessor,
19
19
  )
20
- from async_durable_execution_runner.exceptions import (
20
+ from ...exceptions import (
21
21
  InvalidParameterValueException,
22
22
  )
23
- from async_durable_execution_runner.token import CallbackToken
23
+ from ...token import CallbackToken
24
+
24
25
 
25
26
  if TYPE_CHECKING:
26
- from async_durable_execution_runner.observer import ExecutionNotifier
27
+ from ...observer import ExecutionNotifier
27
28
 
28
29
 
29
30
  class CallbackProcessor(OperationProcessor):
@@ -33,8 +34,8 @@ class CallbackProcessor(OperationProcessor):
33
34
  self,
34
35
  update: OperationUpdate,
35
36
  current_op: Operation | None,
36
- notifier: ExecutionNotifier, # noqa: ARG002
37
- execution_arn: str, # noqa: ARG002
37
+ notifier: ExecutionNotifier,
38
+ execution_arn: str,
38
39
  ) -> Operation:
39
40
  """Process CALLBACK operation update with scheduler integration for activities."""
40
41
  match update.action:
@@ -4,23 +4,22 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- from async_durable_execution.lambda_service import (
7
+ from async_durable_execution.models import (
8
8
  Operation,
9
9
  OperationAction,
10
10
  OperationStatus,
11
11
  OperationUpdate,
12
12
  )
13
-
14
- from async_durable_execution_runner.checkpoint.processors.base import (
13
+ from .base import (
15
14
  OperationProcessor,
16
15
  )
17
- from async_durable_execution_runner.exceptions import (
16
+ from ...exceptions import (
18
17
  InvalidParameterValueException,
19
18
  )
20
19
 
21
20
 
22
21
  if TYPE_CHECKING:
23
- from async_durable_execution_runner.observer import ExecutionNotifier
22
+ from ...observer import ExecutionNotifier
24
23
 
25
24
 
26
25
  class ContextProcessor(OperationProcessor):
@@ -4,20 +4,19 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- from async_durable_execution.lambda_service import (
7
+ from async_durable_execution.models import (
8
8
  ErrorObject,
9
9
  Operation,
10
10
  OperationAction,
11
11
  OperationUpdate,
12
12
  )
13
-
14
- from async_durable_execution_runner.checkpoint.processors.base import (
13
+ from .base import (
15
14
  OperationProcessor,
16
15
  )
17
16
 
18
17
 
19
18
  if TYPE_CHECKING:
20
- from async_durable_execution_runner.observer import ExecutionNotifier
19
+ from ...observer import ExecutionNotifier
21
20
 
22
21
 
23
22
  class ExecutionProcessor(OperationProcessor):
@@ -38,12 +37,8 @@ class ExecutionProcessor(OperationProcessor):
38
37
  )
39
38
  case _:
40
39
  # intentional. actual service will fail any EXECUTION update that is not SUCCEED.
41
- error = (
42
- update.error
43
- if update.error
44
- else ErrorObject.from_message(
45
- "There is no error details but EXECUTION checkpoint action is not SUCCEED."
46
- )
40
+ error = update.error or ErrorObject.from_message(
41
+ "There is no error details but EXECUTION checkpoint action is not SUCCEED."
47
42
  )
48
43
  # All EXECUTION failures go through normal fail path
49
44
  # Timeout/Stop status is set by executor based on the operation that caused it
@@ -2,27 +2,26 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from datetime import UTC, datetime, timedelta
5
+ from datetime import datetime, timedelta, timezone
6
6
  from typing import TYPE_CHECKING
7
7
 
8
- from async_durable_execution.lambda_service import (
8
+ from async_durable_execution.models import (
9
9
  Operation,
10
10
  OperationAction,
11
11
  OperationStatus,
12
12
  OperationUpdate,
13
13
  StepDetails,
14
14
  )
15
-
16
- from async_durable_execution_runner.checkpoint.processors.base import (
15
+ from .base import (
17
16
  OperationProcessor,
18
17
  )
19
- from async_durable_execution_runner.exceptions import (
18
+ from ...exceptions import (
20
19
  InvalidParameterValueException,
21
20
  )
22
21
 
23
22
 
24
23
  if TYPE_CHECKING:
25
- from async_durable_execution_runner.observer import ExecutionNotifier
24
+ from ...observer import ExecutionNotifier
26
25
 
27
26
 
28
27
  class StepProcessor(OperationProcessor):
@@ -50,7 +49,9 @@ class StepProcessor(OperationProcessor):
50
49
  if update.step_options
51
50
  else 0
52
51
  )
53
- next_attempt_time = datetime.now(UTC) + timedelta(seconds=delay)
52
+ next_attempt_time = datetime.now(timezone.utc) + timedelta(
53
+ seconds=delay
54
+ )
54
55
 
55
56
  # Build new step_details with incremented attempt
56
57
  current_attempt = (
@@ -81,7 +82,9 @@ class StepProcessor(OperationProcessor):
81
82
  parent_id=update.parent_id,
82
83
  name=update.name,
83
84
  start_timestamp=(
84
- current_op.start_timestamp if current_op else datetime.now(UTC)
85
+ current_op.start_timestamp
86
+ if current_op
87
+ else datetime.now(timezone.utc)
85
88
  ),
86
89
  end_timestamp=None,
87
90
  sub_type=update.sub_type,
@@ -4,27 +4,26 @@ from __future__ import annotations
4
4
 
5
5
  import logging
6
6
  import os
7
- from datetime import UTC, datetime, timedelta
7
+ from datetime import datetime, timedelta, timezone
8
8
  from typing import TYPE_CHECKING
9
9
 
10
- from async_durable_execution.lambda_service import (
10
+ from async_durable_execution.models import (
11
11
  Operation,
12
12
  OperationAction,
13
13
  OperationStatus,
14
14
  OperationUpdate,
15
15
  WaitDetails,
16
16
  )
17
-
18
- from async_durable_execution_runner.checkpoint.processors.base import (
17
+ from .base import (
19
18
  OperationProcessor,
20
19
  )
21
- from async_durable_execution_runner.exceptions import (
20
+ from ...exceptions import (
22
21
  InvalidParameterValueException,
23
22
  )
24
23
 
25
24
 
26
25
  if TYPE_CHECKING:
27
- from async_durable_execution_runner.observer import ExecutionNotifier
26
+ from ...observer import ExecutionNotifier
28
27
 
29
28
 
30
29
  class WaitProcessor(OperationProcessor):
@@ -47,7 +46,7 @@ class WaitProcessor(OperationProcessor):
47
46
  logging.info("Using DURABLE_EXECUTION_TIME_SCALE: %f", time_scale)
48
47
  scaled_wait_seconds = wait_seconds * time_scale
49
48
 
50
- scheduled_end_timestamp = datetime.now(UTC) + timedelta(
49
+ scheduled_end_timestamp = datetime.now(timezone.utc) + timedelta(
51
50
  seconds=scaled_wait_seconds
52
51
  )
53
52
 
@@ -63,7 +62,7 @@ class WaitProcessor(OperationProcessor):
63
62
  status=OperationStatus.STARTED,
64
63
  parent_id=update.parent_id,
65
64
  name=update.name,
66
- start_timestamp=datetime.now(UTC),
65
+ start_timestamp=datetime.now(timezone.utc),
67
66
  end_timestamp=None,
68
67
  sub_type=update.sub_type,
69
68
  execution_details=None,
@@ -4,28 +4,27 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- from async_durable_execution.lambda_service import (
7
+ from async_durable_execution.models import (
8
8
  Operation,
9
9
  OperationType,
10
10
  OperationUpdate,
11
11
  )
12
-
13
- from async_durable_execution_runner.checkpoint.processors.callback import (
12
+ from .processors.callback import (
14
13
  CallbackProcessor,
15
14
  )
16
- from async_durable_execution_runner.checkpoint.processors.context import (
15
+ from .processors.context import (
17
16
  ContextProcessor,
18
17
  )
19
- from async_durable_execution_runner.checkpoint.processors.execution import (
18
+ from .processors.execution import (
20
19
  ExecutionProcessor,
21
20
  )
22
- from async_durable_execution_runner.checkpoint.processors.step import (
21
+ from .processors.step import (
23
22
  StepProcessor,
24
23
  )
25
- from async_durable_execution_runner.checkpoint.processors.wait import (
24
+ from .processors.wait import (
26
25
  WaitProcessor,
27
26
  )
28
- from async_durable_execution_runner.exceptions import (
27
+ from ..exceptions import (
29
28
  InvalidParameterValueException,
30
29
  )
31
30
 
@@ -33,7 +32,7 @@ from async_durable_execution_runner.exceptions import (
33
32
  if TYPE_CHECKING:
34
33
  from collections.abc import MutableMapping
35
34
 
36
- from async_durable_execution_runner.checkpoint.processors.base import (
35
+ from .processors.base import (
37
36
  OperationProcessor,
38
37
  )
39
38
 
@@ -55,7 +54,7 @@ class OperationTransformer:
55
54
  self,
56
55
  processors: MutableMapping[OperationType, OperationProcessor] | None = None,
57
56
  ):
58
- self.processors = processors if processors else self._DEFAULT_PROCESSORS
57
+ self.processors = processors or self._DEFAULT_PROCESSORS
59
58
 
60
59
  def process_updates(
61
60
  self,