2020from uuid import UUID
2121
2222from SpiffWorkflow .bpmn .specs .mixins .subworkflow_task import SubWorkflowTask
23+ from SpiffWorkflow .util .deep_merge import DeepMerge
2324from SpiffWorkflow .util .copyonwrite import CopyOnWriteDict
2425
2526from ..helpers .bpmn_converter import BpmnConverter
@@ -29,16 +30,18 @@ class TaskConverter(BpmnConverter):
2930 def to_dict (self , task ):
3031 # Optimize serialization by storing only local changes (delta)
3132 # instead of the full materialized data when task has a parent
32- if isinstance ( task . data , CopyOnWriteDict ) and task . parent is not None :
33- # Store only local modifications (delta from parent)
34- task_data = task .data . get_local_data ()
35- delta_serialization = True
33+
34+ if task . parent is None :
35+ data = task .data
36+ delta = {}
3637 else :
37- # Root task or regular dict: serialize full data
38- task_data = task .data .materialize () if isinstance (task .data , CopyOnWriteDict ) else task .data
39- delta_serialization = False
38+ data = {}
39+ delta = {
40+ 'updates' : DeepMerge .get_updated_keys (task .parent .data , task .data ),
41+ 'deletions' : DeepMerge .get_deleted_keys (task .parent .data , task .data ),
42+ }
4043
41- result = {
44+ return {
4245 'id' : str (task .id ),
4346 'parent' : str (task ._parent ) if task .parent is not None else None ,
4447 'children' : [ str (child ) for child in task ._children ],
@@ -47,16 +50,12 @@ def to_dict(self, task):
4750 'task_spec' : task .task_spec .name ,
4851 'triggered' : task .triggered ,
4952 'internal_data' : self .registry .convert (task .internal_data ),
50- 'data' : self .registry .convert (self .registry .clean (task_data )),
53+ 'data' : data ,
54+ 'delta' : delta
5155 }
5256
53- # Mark delta serialization for deserialization
54- if delta_serialization :
55- result ['data_is_delta' ] = True
56-
57- return result
58-
5957 def from_dict (self , dct , workflow ):
58+
6059 task_spec = workflow .spec .task_specs .get (dct ['task_spec' ])
6160 task = self .target_class (workflow , task_spec , state = dct ['state' ], id = UUID (dct ['id' ]))
6261 task ._parent = UUID (dct ['parent' ]) if dct ['parent' ] is not None else None
@@ -65,14 +64,17 @@ def from_dict(self, dct, workflow):
6564 task .triggered = dct ['triggered' ]
6665 task .internal_data = self .registry .restore (dct ['internal_data' ])
6766
68- # Handle delta vs full data serialization
69- restored_data = self .registry .restore (dct ['data' ])
70- if dct .get ('data_is_delta' , False ) and task .parent is not None :
71- # Reconstruct full data from parent + local delta
72- task .data = CopyOnWriteDict (parent = task .parent .data , ** restored_data )
67+ delta = dct .get ('delta' )
68+ if delta :
69+ data = DeepMerge .merge ({}, task .parent .data )
70+ data .update (self .registry .restore (delta .get ('updates' , {})))
71+ for key in delta .get ('deletions' , {}):
72+ if key in data :
73+ del data [key ]
7374 else :
74- # Full data (backward compatible with old serializations)
75- task .data = restored_data
75+ data = self .registry .restore (dct ['data' ])
76+
77+ task .data = data
7678
7779 return task
7880
0 commit comments