33import json
44from dataclasses import replace
55from datetime import UTC , datetime
6- from typing import TYPE_CHECKING
6+ from typing import Any
77from uuid import uuid4
88
99from aws_durable_execution_sdk_python .execution import (
2424 IllegalStateException ,
2525 InvalidParameterValueException ,
2626)
27+ from aws_durable_execution_sdk_python_testing .model import (
28+ StartDurableExecutionInput ,
29+ )
2730from aws_durable_execution_sdk_python_testing .token import CheckpointToken
2831
2932
30- if TYPE_CHECKING :
31- from aws_durable_execution_sdk_python_testing .model import (
32- StartDurableExecutionInput ,
33- )
34-
35-
3633class Execution :
3734 """Execution state."""
3835
@@ -51,7 +48,7 @@ def __init__(
5148 # TODO: this will need to persist/rehydrate depending on inmemory vs sqllite store
5249 self .token_sequence : int = 0
5350 self .is_complete : bool = False
54- self .result : DurableExecutionInvocationOutput | None
51+ self .result : DurableExecutionInvocationOutput | None = None
5552 self .consecutive_failed_invocation_attempts : int = 0
5653
5754 @staticmethod
@@ -63,6 +60,54 @@ def new(input: StartDurableExecutionInput) -> Execution: # noqa: A002
6360 durable_execution_arn = str (uuid4 ()), start_input = input , operations = []
6461 )
6562
63+ def to_dict (self ) -> dict [str , Any ]:
64+ """Serialize execution to dictionary."""
65+ return {
66+ "DurableExecutionArn" : self .durable_execution_arn ,
67+ "StartInput" : self .start_input .to_dict (),
68+ "Operations" : [op .to_dict () for op in self .operations ],
69+ "Updates" : [update .to_dict () for update in self .updates ],
70+ "UsedTokens" : list (self .used_tokens ),
71+ "TokenSequence" : self .token_sequence ,
72+ "IsComplete" : self .is_complete ,
73+ "Result" : self .result .to_dict () if self .result else None ,
74+ "ConsecutiveFailedInvocationAttempts" : self .consecutive_failed_invocation_attempts ,
75+ }
76+
77+ @classmethod
78+ def from_dict (cls , data : dict [str , Any ]) -> Execution :
79+ """Deserialize execution from dictionary."""
80+ # Reconstruct start_input
81+ start_input = StartDurableExecutionInput .from_dict (data ["StartInput" ])
82+
83+ # Reconstruct operations
84+ operations = [Operation .from_dict (op_data ) for op_data in data ["Operations" ]]
85+
86+ # Create execution
87+ execution = cls (
88+ durable_execution_arn = data ["DurableExecutionArn" ],
89+ start_input = start_input ,
90+ operations = operations ,
91+ )
92+
93+ # Set additional fields
94+ execution .updates = [
95+ OperationUpdate .from_dict (update_data ) for update_data in data ["Updates" ]
96+ ]
97+ execution .used_tokens = set (data ["UsedTokens" ])
98+ execution .token_sequence = data ["TokenSequence" ]
99+ execution .is_complete = data ["IsComplete" ]
100+ execution .result = (
101+ DurableExecutionInvocationOutput .from_dict (data ["Result" ])
102+ if data ["Result" ]
103+ else None
104+ )
105+ execution .consecutive_failed_invocation_attempts = data [
106+ "ConsecutiveFailedInvocationAttempts"
107+ ]
108+
109+ return execution
110+
66111 def start (self ) -> None :
67112 # not thread safe, prob should be
68113 if self .start_input .invocation_id is None :
0 commit comments