@@ -23,6 +23,10 @@ def plus_one(_: task.ActivityContext, input: int) -> int:
2323 return input + 1
2424
2525
26+ def plus_two (_ : task .ActivityContext , input : int ) -> int :
27+ return input + 2
28+
29+
2630def single_activity (ctx : task .OrchestrationContext , start_val : int ):
2731 yield ctx .call_activity (plus_one , input = start_val )
2832 return "Success"
@@ -153,6 +157,35 @@ def test_upper_version_worker_succeeds():
153157
154158
155159def test_upper_version_worker_strict_fails ():
160+ # Start a worker, which will connect to the sidecar in a background thread
161+ with DurableTaskSchedulerWorker (host_address = endpoint , secure_channel = True ,
162+ taskhub = taskhub_name , token_credential = None ) as w :
163+ w .add_orchestrator (single_activity )
164+ w .add_activity (plus_one )
165+ w .use_versioning (worker .VersioningOptions (
166+ version = "1.1.0" ,
167+ default_version = "1.1.0" ,
168+ match_strategy = worker .VersionMatchStrategy .STRICT ,
169+ failure_strategy = worker .VersionFailureStrategy .FAIL
170+ ))
171+ w .start ()
172+
173+ task_hub_client = DurableTaskSchedulerClient (host_address = endpoint , secure_channel = True ,
174+ taskhub = taskhub_name , token_credential = None ,
175+ default_version = "1.1.0" )
176+ id = task_hub_client .schedule_new_orchestration (single_activity , input = 1 , version = "1.0.0" )
177+ state = task_hub_client .wait_for_orchestration_completion (
178+ id , timeout = 30 )
179+
180+ assert state is not None
181+ assert state .name == task .get_name (single_activity )
182+ assert state .instance_id == id
183+ assert state .runtime_status == client .OrchestrationStatus .FAILED
184+ assert state .failure_details is not None
185+ assert state .failure_details .message .find ("The orchestration version '1.0.0' does not match the worker version '1.1.0'." ) >= 0
186+
187+
188+ def test_reject_abandons_and_reprocess ():
156189 # Start a worker, which will connect to the sidecar in a background thread
157190 instance_id : str = ''
158191 thrown = False
@@ -206,36 +239,58 @@ def test_upper_version_worker_strict_fails():
206239 assert state .failure_details is None
207240
208241
209- def test_reject_abandons_and_reprocess ():
242+ def multiversion_sequence (ctx : task .OrchestrationContext , start_val : int ):
243+ if ctx .version == "1.0.0" :
244+ result = yield ctx .call_activity (plus_one , input = start_val )
245+ elif ctx .version == "1.1.0" :
246+ result = yield ctx .call_activity (plus_two , input = start_val )
247+ else :
248+ raise ValueError (f"Unsupported version: { ctx .version } " )
249+ return result
250+
251+
252+ def test_multiversion_orchestration_succeeds ():
210253 # Start a worker, which will connect to the sidecar in a background thread
211254 with DurableTaskSchedulerWorker (host_address = endpoint , secure_channel = True ,
212255 taskhub = taskhub_name , token_credential = None ) as w :
213- w .add_orchestrator (single_activity )
256+ w .add_orchestrator (multiversion_sequence )
214257 w .add_activity (plus_one )
258+ w .add_activity (plus_two )
215259 w .use_versioning (worker .VersioningOptions (
216260 version = "1.1.0" ,
217261 default_version = "1.1.0" ,
218- match_strategy = worker .VersionMatchStrategy .STRICT ,
262+ match_strategy = worker .VersionMatchStrategy .CURRENT_OR_OLDER ,
219263 failure_strategy = worker .VersionFailureStrategy .FAIL
220264 ))
221265 w .start ()
222266
223267 task_hub_client = DurableTaskSchedulerClient (host_address = endpoint , secure_channel = True ,
224268 taskhub = taskhub_name , token_credential = None ,
225269 default_version = "1.1.0" )
226- id = task_hub_client .schedule_new_orchestration (single_activity , input = 1 , version = "1.0.0" )
227- state = task_hub_client .wait_for_orchestration_completion (
228- id , timeout = 30 )
270+ id = task_hub_client .schedule_new_orchestration (multiversion_sequence , input = 1 , version = "1.0.0" )
271+ state = task_hub_client .wait_for_orchestration_completion (id , timeout = 30 )
229272
230- assert state is not None
231- assert state .name == task .get_name (single_activity )
232- assert state .instance_id == id
233- assert state .runtime_status == client .OrchestrationStatus .FAILED
234- assert state .failure_details is not None
235- assert state .failure_details .message .find ("The orchestration version '1.0.0' does not match the worker version '1.1.0'." ) >= 0
273+ id_2 = task_hub_client .schedule_new_orchestration (multiversion_sequence , input = 1 , version = "1.1.0" )
274+ state_2 = task_hub_client .wait_for_orchestration_completion (id_2 , timeout = 30 )
236275
276+ print (state .failure_details .message if state and state .failure_details else "State is None" )
277+ print (state_2 .failure_details .message if state_2 and state_2 .failure_details else "State is None" )
237278
238- # Sub-orchestration tests
279+ assert state is not None
280+ assert state .name == task .get_name (multiversion_sequence )
281+ assert state .instance_id == id
282+ assert state .runtime_status == client .OrchestrationStatus .COMPLETED
283+ assert state .failure_details is None
284+ assert state .serialized_input == json .dumps (1 )
285+ assert state .serialized_output == json .dumps (2 )
286+
287+ assert state_2 is not None
288+ assert state_2 .name == task .get_name (multiversion_sequence )
289+ assert state_2 .instance_id == id_2
290+ assert state_2 .runtime_status == client .OrchestrationStatus .COMPLETED
291+ assert state_2 .failure_details is None
292+ assert state_2 .serialized_input == json .dumps (1 )
293+ assert state_2 .serialized_output == json .dumps (3 )
239294
240295
241296def sequence_suborchestator (ctx : task .OrchestrationContext , start_val : int ):
0 commit comments