aws-durable-execution-sdk-python-testing 1.2.0__py3-none-any.whl → 1.3.0__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 (49) hide show
  1. aws_durable_execution_sdk_python_testing/__about__.py +1 -1
  2. aws_durable_execution_sdk_python_testing/checkpoint/core.py +171 -0
  3. aws_durable_execution_sdk_python_testing/checkpoint/effects.py +61 -0
  4. aws_durable_execution_sdk_python_testing/checkpoint/processor.py +124 -45
  5. aws_durable_execution_sdk_python_testing/checkpoint/processors/base.py +40 -14
  6. aws_durable_execution_sdk_python_testing/checkpoint/processors/callback.py +5 -2
  7. aws_durable_execution_sdk_python_testing/checkpoint/processors/context.py +6 -0
  8. aws_durable_execution_sdk_python_testing/checkpoint/processors/execution.py +4 -9
  9. aws_durable_execution_sdk_python_testing/checkpoint/processors/invoke.py +139 -0
  10. aws_durable_execution_sdk_python_testing/checkpoint/processors/step.py +15 -21
  11. aws_durable_execution_sdk_python_testing/checkpoint/processors/wait.py +10 -16
  12. aws_durable_execution_sdk_python_testing/checkpoint/transformer.py +145 -48
  13. aws_durable_execution_sdk_python_testing/checkpoint/validators/checkpoint.py +65 -8
  14. aws_durable_execution_sdk_python_testing/checkpoint/validators/operations/invoke.py +79 -18
  15. aws_durable_execution_sdk_python_testing/child_dispatcher.py +828 -0
  16. aws_durable_execution_sdk_python_testing/cli.py +48 -1
  17. aws_durable_execution_sdk_python_testing/client.py +21 -10
  18. aws_durable_execution_sdk_python_testing/clock.py +69 -0
  19. aws_durable_execution_sdk_python_testing/exceptions.py +14 -0
  20. aws_durable_execution_sdk_python_testing/execution.py +583 -49
  21. aws_durable_execution_sdk_python_testing/executor.py +1813 -349
  22. aws_durable_execution_sdk_python_testing/invoker.py +356 -85
  23. aws_durable_execution_sdk_python_testing/model.py +81 -73
  24. aws_durable_execution_sdk_python_testing/observer.py +100 -88
  25. aws_durable_execution_sdk_python_testing/runner.py +407 -30
  26. aws_durable_execution_sdk_python_testing/scheduler.py +38 -13
  27. aws_durable_execution_sdk_python_testing/stores/filesystem.py +10 -2
  28. aws_durable_execution_sdk_python_testing/stores/sqlite.py +18 -6
  29. aws_durable_execution_sdk_python_testing/threads.py +157 -0
  30. aws_durable_execution_sdk_python_testing/token.py +11 -2
  31. aws_durable_execution_sdk_python_testing/web/handlers.py +33 -7
  32. aws_durable_execution_sdk_python_testing/web/routes.py +14 -6
  33. aws_durable_execution_sdk_python_testing/web/serialization.py +1 -2
  34. aws_durable_execution_sdk_python_testing/web/server.py +1 -1
  35. aws_durable_execution_sdk_python_testing/worker/__init__.py +9 -0
  36. aws_durable_execution_sdk_python_testing/worker/checkpoint_tasks.py +119 -0
  37. aws_durable_execution_sdk_python_testing/worker/execution_worker.py +117 -0
  38. aws_durable_execution_sdk_python_testing/worker/lane.py +118 -0
  39. aws_durable_execution_sdk_python_testing/worker/registry.py +124 -0
  40. aws_durable_execution_sdk_python_testing/worker/status.py +27 -0
  41. aws_durable_execution_sdk_python_testing/worker/task.py +57 -0
  42. {aws_durable_execution_sdk_python_testing-1.2.0.dist-info → aws_durable_execution_sdk_python_testing-1.3.0.dist-info}/METADATA +50 -58
  43. aws_durable_execution_sdk_python_testing-1.3.0.dist-info/RECORD +64 -0
  44. {aws_durable_execution_sdk_python_testing-1.2.0.dist-info → aws_durable_execution_sdk_python_testing-1.3.0.dist-info}/WHEEL +1 -1
  45. aws_durable_execution_sdk_python_testing/checkpoint/validators/transitions.py +0 -66
  46. aws_durable_execution_sdk_python_testing-1.2.0.dist-info/RECORD +0 -52
  47. {aws_durable_execution_sdk_python_testing-1.2.0.dist-info/licenses → aws_durable_execution_sdk_python_testing}/LICENSE +0 -0
  48. {aws_durable_execution_sdk_python_testing-1.2.0.dist-info/licenses → aws_durable_execution_sdk_python_testing}/NOTICE +0 -0
  49. {aws_durable_execution_sdk_python_testing-1.2.0.dist-info → aws_durable_execution_sdk_python_testing-1.3.0.dist-info}/entry_points.txt +0 -0
@@ -2,55 +2,116 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from typing import TYPE_CHECKING
6
+
5
7
  from aws_durable_execution_sdk_python.lambda_service import (
6
8
  Operation,
7
9
  OperationAction,
8
- OperationStatus,
9
10
  OperationUpdate,
10
11
  )
11
12
 
13
+ from aws_durable_execution_sdk_python_testing.child_dispatcher import (
14
+ CHAINED_INVOKE_DIFFERENT_ACCOUNT_MESSAGE,
15
+ CHAINED_INVOKE_DIFFERENT_REGION_MESSAGE,
16
+ INVALID_FUNCTION_ARN_MESSAGE_FORMAT,
17
+ INVALID_TENANT_ID_MESSAGE,
18
+ FunctionTarget,
19
+ is_valid_tenant_id,
20
+ parse_function_target,
21
+ )
12
22
  from aws_durable_execution_sdk_python_testing.exceptions import (
13
23
  InvalidParameterValueException,
14
24
  )
15
25
 
26
+ if TYPE_CHECKING:
27
+ from aws_durable_execution_sdk_python_testing.execution import Execution
28
+
16
29
 
17
30
  VALID_ACTIONS_FOR_INVOKE = frozenset(
18
31
  [
19
32
  OperationAction.START,
20
- OperationAction.CANCEL,
21
33
  ]
22
34
  )
23
35
 
24
36
 
25
37
  class ChainedInvokeOperationValidator:
26
- """Validates INVOKE operation transitions."""
38
+ """Validates INVOKE operation transitions.
27
39
 
28
- _ALLOWED_STATUS_TO_CANCEL = frozenset(
29
- [
30
- OperationStatus.STARTED,
31
- ]
32
- )
40
+ START is the only accepted action: a chained invoke completes through
41
+ the invoked function's terminal state, not through a handler
42
+ checkpoint. START also validates the options, as the service does:
43
+ the target must be a well-formed Lambda function name or ARN in the
44
+ parent's account and region, and a TenantId must satisfy the API
45
+ constraint.
46
+ """
33
47
 
34
48
  @staticmethod
35
- def validate(current_state: Operation | None, update: OperationUpdate) -> None:
49
+ def validate(
50
+ current_state: Operation | None,
51
+ update: OperationUpdate,
52
+ execution: Execution,
53
+ ) -> None:
36
54
  """Validate INVOKE operation update."""
37
55
  match update.action:
38
56
  case OperationAction.START:
39
57
  if current_state is not None:
40
58
  msg_invoke_exists: str = (
41
- "Cannot start an INVOKE that already exist."
59
+ "Cannot start a CHAINED_INVOKE operation that already exists."
42
60
  )
43
61
 
44
62
  raise InvalidParameterValueException(msg_invoke_exists)
45
- case OperationAction.CANCEL:
46
- if (
47
- current_state is None
48
- or current_state.status
49
- not in ChainedInvokeOperationValidator._ALLOWED_STATUS_TO_CANCEL
63
+ if update.chained_invoke_options is None:
64
+ msg_options_required: str = (
65
+ "Update for CHAINED_INVOKE operation requires "
66
+ "ChainedInvokeOptions."
67
+ )
68
+ raise InvalidParameterValueException(msg_options_required)
69
+ ChainedInvokeOperationValidator._validate_target(
70
+ update.chained_invoke_options.function_name, execution
71
+ )
72
+ # The API model types TenantId as a string. A value of
73
+ # another type is a validation error, not a server error.
74
+ tenant_id: str | None = update.chained_invoke_options.tenant_id
75
+ if tenant_id is not None and (
76
+ not isinstance(tenant_id, str) or not is_valid_tenant_id(tenant_id)
50
77
  ):
51
- msg_invoke_cancel: str = "Cannot cancel an INVOKE that does not exist or has already completed."
52
- raise InvalidParameterValueException(msg_invoke_cancel)
78
+ raise InvalidParameterValueException(INVALID_TENANT_ID_MESSAGE)
53
79
  case _:
54
- msg_invoke_invalid: str = "Invalid INVOKE action."
80
+ msg_invoke_invalid: str = "Invalid action for CHAINED_INVOKE operation."
55
81
 
56
82
  raise InvalidParameterValueException(msg_invoke_invalid)
83
+
84
+ @staticmethod
85
+ def _validate_target(function_name: str, execution: Execution) -> None:
86
+ """Reject a malformed target or one in another account or region.
87
+
88
+ The region check applies only when the execution recorded a
89
+ region; an execution built without one skips it.
90
+ """
91
+ # The API model requires FunctionName as a string. A missing or
92
+ # non-string value is a validation error, not a server error.
93
+ if not isinstance(function_name, str):
94
+ raise InvalidParameterValueException(
95
+ INVALID_FUNCTION_ARN_MESSAGE_FORMAT.format(function_name)
96
+ )
97
+ try:
98
+ target: FunctionTarget = parse_function_target(function_name)
99
+ except ValueError as err:
100
+ raise InvalidParameterValueException(
101
+ INVALID_FUNCTION_ARN_MESSAGE_FORMAT.format(function_name)
102
+ ) from err
103
+ if (
104
+ target.account_id is not None
105
+ and target.account_id != execution.start_input.account_id
106
+ ):
107
+ raise InvalidParameterValueException(
108
+ CHAINED_INVOKE_DIFFERENT_ACCOUNT_MESSAGE
109
+ )
110
+ if (
111
+ target.region is not None
112
+ and execution.region is not None
113
+ and target.region != execution.region
114
+ ):
115
+ raise InvalidParameterValueException(
116
+ CHAINED_INVOKE_DIFFERENT_REGION_MESSAGE
117
+ )