1+ from datetime import datetime , timedelta
12from .orchestrator_test_utils \
23 import assert_orchestration_state_equals , get_orchestration_state_result , assert_valid_schema
34from tests .test_utils .ContextBuilder import ContextBuilder
@@ -20,6 +21,49 @@ def generator_function(context):
2021
2122 return outputs
2223
24+ def generator_function_time_is_not_none (context ):
25+ outputs = []
26+
27+ now = context .current_utc_datetime
28+ if not now :
29+ raise Exception ("No time! 1st attempt" )
30+ task1 = yield context .call_activity ("Hello" , "Tokyo" )
31+
32+ now = context .current_utc_datetime
33+ if not now :
34+ raise Exception ("No time! 2nd attempt" )
35+ task2 = yield context .call_activity ("Hello" , "Seattle" )
36+
37+ now = context .current_utc_datetime
38+ if not now :
39+ raise Exception ("No time! 3rd attempt" )
40+ task3 = yield context .call_activity ("Hello" , "London" )
41+
42+ now = context .current_utc_datetime
43+ if not now :
44+ raise Exception ("No time! 4th attempt" )
45+
46+ outputs .append (task1 )
47+ outputs .append (task2 )
48+ outputs .append (task3 )
49+
50+ return outputs
51+
52+ def generator_function_time_gather (context ):
53+ outputs = []
54+
55+ outputs .append (context .current_utc_datetime .strftime ("%m/%d/%Y, %H:%M:%S" ))
56+ yield context .call_activity ("Hello" , "Tokyo" )
57+
58+ outputs .append (context .current_utc_datetime .strftime ("%m/%d/%Y, %H:%M:%S" ))
59+ yield context .call_activity ("Hello" , "Seattle" )
60+
61+ outputs .append (context .current_utc_datetime .strftime ("%m/%d/%Y, %H:%M:%S" ))
62+ yield context .call_activity ("Hello" , "London" )
63+
64+ outputs .append (context .current_utc_datetime .strftime ("%m/%d/%Y, %H:%M:%S" ))
65+ return outputs
66+
2367def generator_function_rasing_ex (context ):
2468 outputs = []
2569
@@ -220,3 +264,92 @@ def test_tokyo_and_seattle_and_london_with_serialization_state():
220264
221265 assert_valid_schema (result )
222266 assert_orchestration_state_equals (expected , result )
267+
268+ def test_utc_time_is_never_none ():
269+ """Tests an orchestrator that errors out if its current_utc_datetime is ever None.
270+
271+ If we receive all activity results, it means we never error'ed out. Our test has
272+ a history events array with identical timestamps, simulating events arriving
273+ very close to one another."""
274+
275+ # we set `increase_time` to False to make sure the changes are resilient
276+ # to undistinguishable timestamps (events arrive very close to each other)
277+ context_builder = ContextBuilder ('test_simple_function' , increase_time = False )
278+ add_hello_completed_events (context_builder , 0 , "\" Hello Tokyo!\" " )
279+ add_hello_completed_events (context_builder , 1 , "\" Hello Seattle!\" " )
280+ add_hello_completed_events (context_builder , 2 , "\" Hello London!\" " )
281+
282+ result = get_orchestration_state_result (
283+ context_builder , generator_function_deterministic_utc_time )
284+
285+ expected_state = base_expected_state (
286+ ['Hello Tokyo!' , 'Hello Seattle!' , 'Hello London!' ])
287+ add_hello_action (expected_state , 'Tokyo' )
288+ add_hello_action (expected_state , 'Seattle' )
289+ add_hello_action (expected_state , 'London' )
290+ expected_state ._is_done = True
291+ expected = expected_state .to_json ()
292+
293+ assert_valid_schema (result )
294+ assert_orchestration_state_equals (expected , result )
295+
296+ def test_utc_time_is_never_none ():
297+ """Tests an orchestrator that errors out if its current_utc_datetime is ever None.
298+
299+ If we receive all activity results, it means we never error'ed out. Our test has
300+ a history events array with identical timestamps, simulating events arriving
301+ very close to one another."""
302+
303+ # we set `increase_time` to False to make sure the changes are resilient
304+ # to undistinguishable timestamps (events arrive very close to each other)
305+ context_builder = ContextBuilder ('test_simple_function' , increase_time = False )
306+ add_hello_completed_events (context_builder , 0 , "\" Hello Tokyo!\" " )
307+ add_hello_completed_events (context_builder , 1 , "\" Hello Seattle!\" " )
308+ add_hello_completed_events (context_builder , 2 , "\" Hello London!\" " )
309+
310+ result = get_orchestration_state_result (
311+ context_builder , generator_function_time_is_not_none )
312+
313+ expected_state = base_expected_state (
314+ ['Hello Tokyo!' , 'Hello Seattle!' , 'Hello London!' ])
315+ add_hello_action (expected_state , 'Tokyo' )
316+ add_hello_action (expected_state , 'Seattle' )
317+ add_hello_action (expected_state , 'London' )
318+ expected_state ._is_done = True
319+ expected = expected_state .to_json ()
320+
321+ assert_valid_schema (result )
322+ assert_orchestration_state_equals (expected , result )
323+
324+ def test_utc_time_updates_correctly ():
325+ """Tests that current_utc_datetime updates correctly"""
326+
327+ now = datetime .utcnow ()
328+ # the first orchestrator-started event starts 1 second after `now`
329+ context_builder = ContextBuilder ('test_simple_function' , starting_time = now )
330+ add_hello_completed_events (context_builder , 0 , "\" Hello Tokyo!\" " )
331+ add_hello_completed_events (context_builder , 1 , "\" Hello Seattle!\" " )
332+ add_hello_completed_events (context_builder , 2 , "\" Hello London!\" " )
333+
334+ result = get_orchestration_state_result (
335+ context_builder , generator_function_time_gather )
336+
337+ # In the expected history, the orchestrator starts again every 4 seconds
338+ # The current_utc_datetime should update to the orchestrator start event timestamp
339+ num_restarts = 3
340+ expected_utc_time = now + timedelta (seconds = 1 )
341+ outputs = [expected_utc_time .strftime ("%m/%d/%Y, %H:%M:%S" )]
342+ for _ in range (num_restarts ):
343+ expected_utc_time += timedelta (seconds = 4 )
344+ outputs .append (expected_utc_time .strftime ("%m/%d/%Y, %H:%M:%S" ))
345+
346+ expected_state = base_expected_state (outputs )
347+ add_hello_action (expected_state , 'Tokyo' )
348+ add_hello_action (expected_state , 'Seattle' )
349+ add_hello_action (expected_state , 'London' )
350+ expected_state ._is_done = True
351+ expected = expected_state .to_json ()
352+
353+ assert_valid_schema (result )
354+ assert_orchestration_state_equals (expected , result )
355+
0 commit comments