azure-functions-durable 1.2.9__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 (104) hide show
  1. azure/durable_functions/__init__.py +81 -81
  2. azure/durable_functions/constants.py +9 -9
  3. azure/durable_functions/decorators/__init__.py +3 -3
  4. azure/durable_functions/decorators/durable_app.py +260 -249
  5. azure/durable_functions/decorators/metadata.py +109 -109
  6. azure/durable_functions/entity.py +129 -125
  7. azure/durable_functions/models/DurableEntityContext.py +201 -201
  8. azure/durable_functions/models/DurableHttpRequest.py +58 -58
  9. azure/durable_functions/models/DurableOrchestrationBindings.py +66 -66
  10. azure/durable_functions/models/DurableOrchestrationClient.py +812 -781
  11. azure/durable_functions/models/DurableOrchestrationContext.py +761 -707
  12. azure/durable_functions/models/DurableOrchestrationStatus.py +156 -156
  13. azure/durable_functions/models/EntityStateResponse.py +23 -23
  14. azure/durable_functions/models/FunctionContext.py +7 -7
  15. azure/durable_functions/models/OrchestrationRuntimeStatus.py +32 -32
  16. azure/durable_functions/models/OrchestratorState.py +117 -116
  17. azure/durable_functions/models/PurgeHistoryResult.py +33 -33
  18. azure/durable_functions/models/ReplaySchema.py +9 -8
  19. azure/durable_functions/models/RetryOptions.py +69 -69
  20. azure/durable_functions/models/RpcManagementOptions.py +86 -86
  21. azure/durable_functions/models/Task.py +540 -426
  22. azure/durable_functions/models/TaskOrchestrationExecutor.py +352 -336
  23. azure/durable_functions/models/TokenSource.py +56 -56
  24. azure/durable_functions/models/__init__.py +26 -24
  25. azure/durable_functions/models/actions/Action.py +23 -23
  26. azure/durable_functions/models/actions/ActionType.py +18 -18
  27. azure/durable_functions/models/actions/CallActivityAction.py +41 -41
  28. azure/durable_functions/models/actions/CallActivityWithRetryAction.py +45 -45
  29. azure/durable_functions/models/actions/CallEntityAction.py +46 -46
  30. azure/durable_functions/models/actions/CallHttpAction.py +35 -35
  31. azure/durable_functions/models/actions/CallSubOrchestratorAction.py +40 -40
  32. azure/durable_functions/models/actions/CallSubOrchestratorWithRetryAction.py +44 -44
  33. azure/durable_functions/models/actions/CompoundAction.py +35 -35
  34. azure/durable_functions/models/actions/ContinueAsNewAction.py +36 -36
  35. azure/durable_functions/models/actions/CreateTimerAction.py +48 -48
  36. azure/durable_functions/models/actions/NoOpAction.py +35 -35
  37. azure/durable_functions/models/actions/SignalEntityAction.py +47 -47
  38. azure/durable_functions/models/actions/WaitForExternalEventAction.py +63 -63
  39. azure/durable_functions/models/actions/WhenAllAction.py +14 -14
  40. azure/durable_functions/models/actions/WhenAnyAction.py +14 -14
  41. azure/durable_functions/models/actions/__init__.py +24 -24
  42. azure/durable_functions/models/entities/EntityState.py +74 -74
  43. azure/durable_functions/models/entities/OperationResult.py +94 -76
  44. azure/durable_functions/models/entities/RequestMessage.py +53 -53
  45. azure/durable_functions/models/entities/ResponseMessage.py +48 -48
  46. azure/durable_functions/models/entities/Signal.py +62 -62
  47. azure/durable_functions/models/entities/__init__.py +17 -17
  48. azure/durable_functions/models/history/HistoryEvent.py +92 -92
  49. azure/durable_functions/models/history/HistoryEventType.py +27 -27
  50. azure/durable_functions/models/history/__init__.py +8 -8
  51. azure/durable_functions/models/utils/__init__.py +7 -7
  52. azure/durable_functions/models/utils/entity_utils.py +103 -91
  53. azure/durable_functions/models/utils/http_utils.py +80 -69
  54. azure/durable_functions/models/utils/json_utils.py +96 -56
  55. azure/durable_functions/orchestrator.py +73 -71
  56. azure/durable_functions/testing/OrchestratorGeneratorWrapper.py +42 -0
  57. azure/durable_functions/testing/__init__.py +6 -0
  58. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/LICENSE +21 -21
  59. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/METADATA +59 -58
  60. azure_functions_durable-1.3.0.dist-info/RECORD +103 -0
  61. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/WHEEL +1 -1
  62. tests/models/test_DecoratorMetadata.py +135 -135
  63. tests/models/test_Decorators.py +107 -107
  64. tests/models/test_DurableOrchestrationBindings.py +68 -68
  65. tests/models/test_DurableOrchestrationClient.py +730 -730
  66. tests/models/test_DurableOrchestrationContext.py +102 -102
  67. tests/models/test_DurableOrchestrationStatus.py +59 -59
  68. tests/models/test_OrchestrationState.py +28 -28
  69. tests/models/test_RpcManagementOptions.py +79 -79
  70. tests/models/test_TokenSource.py +10 -10
  71. tests/orchestrator/models/OrchestrationInstance.py +18 -18
  72. tests/orchestrator/orchestrator_test_utils.py +130 -130
  73. tests/orchestrator/schemas/OrchetrationStateSchema.py +66 -66
  74. tests/orchestrator/test_call_http.py +235 -176
  75. tests/orchestrator/test_continue_as_new.py +67 -67
  76. tests/orchestrator/test_create_timer.py +126 -126
  77. tests/orchestrator/test_entity.py +397 -395
  78. tests/orchestrator/test_external_event.py +53 -53
  79. tests/orchestrator/test_fan_out_fan_in.py +175 -175
  80. tests/orchestrator/test_is_replaying_flag.py +101 -101
  81. tests/orchestrator/test_retries.py +308 -308
  82. tests/orchestrator/test_sequential_orchestrator.py +841 -841
  83. tests/orchestrator/test_sequential_orchestrator_custom_status.py +119 -119
  84. tests/orchestrator/test_sequential_orchestrator_with_retry.py +465 -465
  85. tests/orchestrator/test_serialization.py +30 -30
  86. tests/orchestrator/test_sub_orchestrator.py +95 -95
  87. tests/orchestrator/test_sub_orchestrator_with_retry.py +129 -129
  88. tests/orchestrator/test_task_any.py +60 -60
  89. tests/tasks/tasks_test_utils.py +17 -17
  90. tests/tasks/test_long_timers.py +70 -0
  91. tests/tasks/test_new_uuid.py +34 -34
  92. tests/test_utils/ContextBuilder.py +174 -174
  93. tests/test_utils/EntityContextBuilder.py +56 -56
  94. tests/test_utils/constants.py +1 -1
  95. tests/test_utils/json_utils.py +30 -30
  96. tests/test_utils/testClasses.py +56 -56
  97. tests/utils/__init__.py +1 -0
  98. tests/utils/test_entity_utils.py +24 -0
  99. azure_functions_durable-1.2.9.data/data/_manifest/bsi.json +0 -1
  100. azure_functions_durable-1.2.9.data/data/_manifest/manifest.cat +0 -0
  101. azure_functions_durable-1.2.9.data/data/_manifest/manifest.spdx.json +0 -11985
  102. azure_functions_durable-1.2.9.data/data/_manifest/manifest.spdx.json.sha256 +0 -1
  103. azure_functions_durable-1.2.9.dist-info/RECORD +0 -102
  104. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/top_level.txt +0 -0
@@ -1,31 +1,31 @@
1
- from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
- from tests.test_utils.ContextBuilder import ContextBuilder
3
- from .orchestrator_test_utils \
4
- import get_orchestration_state_result, assert_orchestration_state_equals, assert_valid_schema
5
- from azure.durable_functions.models.OrchestratorState import OrchestratorState
6
-
7
- def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
8
- return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
9
-
10
- def generator_function(context):
11
- return False
12
-
13
- def test_serialization_of_False():
14
- """Test that an orchestrator can return False."""
15
-
16
- context_builder = ContextBuilder("serialize False")
17
-
18
- result = get_orchestration_state_result(
19
- context_builder, generator_function)
20
-
21
- expected_state = base_expected_state(output=False)
22
-
23
- expected_state._is_done = True
24
- expected = expected_state.to_json()
25
-
26
- # Since we're essentially testing the `to_json` functionality,
27
- # we explicitely ensure that the output is set
28
- expected["output"] = False
29
-
30
- assert_valid_schema(result)
1
+ from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
+ from tests.test_utils.ContextBuilder import ContextBuilder
3
+ from .orchestrator_test_utils \
4
+ import get_orchestration_state_result, assert_orchestration_state_equals, assert_valid_schema
5
+ from azure.durable_functions.models.OrchestratorState import OrchestratorState
6
+
7
+ def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
8
+ return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
9
+
10
+ def generator_function(context):
11
+ return False
12
+
13
+ def test_serialization_of_False():
14
+ """Test that an orchestrator can return False."""
15
+
16
+ context_builder = ContextBuilder("serialize False")
17
+
18
+ result = get_orchestration_state_result(
19
+ context_builder, generator_function)
20
+
21
+ expected_state = base_expected_state(output=False)
22
+
23
+ expected_state._is_done = True
24
+ expected = expected_state.to_json()
25
+
26
+ # Since we're essentially testing the `to_json` functionality,
27
+ # we explicitely ensure that the output is set
28
+ expected["output"] = False
29
+
30
+ assert_valid_schema(result)
31
31
  assert_orchestration_state_equals(expected, result)
@@ -1,95 +1,95 @@
1
- from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
- from .orchestrator_test_utils \
3
- import assert_orchestration_state_equals, get_orchestration_state_result, assert_valid_schema
4
- from tests.test_utils.ContextBuilder import ContextBuilder
5
- from azure.durable_functions.models.OrchestratorState import OrchestratorState
6
- from azure.durable_functions.models.actions.CallSubOrchestratorAction \
7
- import CallSubOrchestratorAction
8
- import azure.durable_functions as df
9
- import azure.functions as func
10
-
11
- app = df.DFApp(http_auth_level=func.AuthLevel.ANONYMOUS)
12
-
13
- def generator_function(context):
14
- outputs = []
15
- task1 = yield context.call_sub_orchestrator("HelloSubOrchestrator", "Tokyo")
16
- task2 = yield context.call_sub_orchestrator("HelloSubOrchestrator", "Seattle")
17
- task3 = yield context.call_sub_orchestrator("HelloSubOrchestrator", "London")
18
-
19
- outputs.append(task1)
20
- outputs.append(task2)
21
- outputs.append(task3)
22
-
23
- return outputs
24
-
25
- def generator_function_call_by_function_name(context):
26
- outputs = []
27
- task1 = yield context.call_sub_orchestrator(HelloSubOrchestrator, "Tokyo")
28
- task2 = yield context.call_sub_orchestrator(HelloSubOrchestrator, "Seattle")
29
- task3 = yield context.call_sub_orchestrator(HelloSubOrchestrator, "London")
30
-
31
- outputs.append(task1)
32
- outputs.append(task2)
33
- outputs.append(task3)
34
-
35
- return outputs
36
-
37
- @app.orchestration_trigger(context_name="context")
38
- def HelloSubOrchestrator(context):
39
- return "Hello" + context
40
-
41
- def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
42
- return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
43
-
44
-
45
- def add_hello_suborch_action(state: OrchestratorState, input_: str):
46
- action = CallSubOrchestratorAction(function_name='HelloSubOrchestrator', _input=input_)
47
- state.actions.append([action])
48
-
49
-
50
- def add_hello_suborch_completed_events(
51
- context_builder: ContextBuilder, id_: int, result: str):
52
- context_builder.add_sub_orchestrator_started_event(name="HelloSubOrchestrator", id_=id_,input_="")
53
- context_builder.add_orchestrator_completed_event()
54
- context_builder.add_orchestrator_started_event()
55
- context_builder.add_sub_orchestrator_completed_event(result=result, id_=id_)
56
-
57
- def test_tokyo_and_seattle_and_london_state():
58
- context_builder = ContextBuilder('test_simple_function')
59
- add_hello_suborch_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
60
- add_hello_suborch_completed_events(context_builder, 1, "\"Hello Seattle!\"")
61
- add_hello_suborch_completed_events(context_builder, 2, "\"Hello London!\"")
62
-
63
- result = get_orchestration_state_result(
64
- context_builder, generator_function)
65
-
66
- expected_state = base_expected_state(
67
- ['Hello Tokyo!', 'Hello Seattle!', 'Hello London!'])
68
- add_hello_suborch_action(expected_state, 'Tokyo')
69
- add_hello_suborch_action(expected_state, 'Seattle')
70
- add_hello_suborch_action(expected_state, 'London')
71
- expected_state._is_done = True
72
- expected = expected_state.to_json()
73
-
74
- #assert_valid_schema(result)
75
- assert_orchestration_state_equals(expected, result)
76
-
77
- def test_call_suborchestrator_by_name():
78
- context_builder = ContextBuilder('test_call_suborchestrator_by_name')
79
- add_hello_suborch_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
80
- add_hello_suborch_completed_events(context_builder, 1, "\"Hello Seattle!\"")
81
- add_hello_suborch_completed_events(context_builder, 2, "\"Hello London!\"")
82
-
83
- result = get_orchestration_state_result(
84
- context_builder, generator_function_call_by_function_name)
85
-
86
- expected_state = base_expected_state(
87
- ['Hello Tokyo!', 'Hello Seattle!', 'Hello London!'])
88
- add_hello_suborch_action(expected_state, 'Tokyo')
89
- add_hello_suborch_action(expected_state, 'Seattle')
90
- add_hello_suborch_action(expected_state, 'London')
91
- expected_state._is_done = True
92
- expected = expected_state.to_json()
93
-
94
- #assert_valid_schema(result)
95
- assert_orchestration_state_equals(expected, result)
1
+ from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
+ from .orchestrator_test_utils \
3
+ import assert_orchestration_state_equals, get_orchestration_state_result, assert_valid_schema
4
+ from tests.test_utils.ContextBuilder import ContextBuilder
5
+ from azure.durable_functions.models.OrchestratorState import OrchestratorState
6
+ from azure.durable_functions.models.actions.CallSubOrchestratorAction \
7
+ import CallSubOrchestratorAction
8
+ import azure.durable_functions as df
9
+ import azure.functions as func
10
+
11
+ app = df.DFApp(http_auth_level=func.AuthLevel.ANONYMOUS)
12
+
13
+ def generator_function(context):
14
+ outputs = []
15
+ task1 = yield context.call_sub_orchestrator("HelloSubOrchestrator", "Tokyo")
16
+ task2 = yield context.call_sub_orchestrator("HelloSubOrchestrator", "Seattle")
17
+ task3 = yield context.call_sub_orchestrator("HelloSubOrchestrator", "London")
18
+
19
+ outputs.append(task1)
20
+ outputs.append(task2)
21
+ outputs.append(task3)
22
+
23
+ return outputs
24
+
25
+ def generator_function_call_by_function_name(context):
26
+ outputs = []
27
+ task1 = yield context.call_sub_orchestrator(HelloSubOrchestrator, "Tokyo")
28
+ task2 = yield context.call_sub_orchestrator(HelloSubOrchestrator, "Seattle")
29
+ task3 = yield context.call_sub_orchestrator(HelloSubOrchestrator, "London")
30
+
31
+ outputs.append(task1)
32
+ outputs.append(task2)
33
+ outputs.append(task3)
34
+
35
+ return outputs
36
+
37
+ @app.orchestration_trigger(context_name="context")
38
+ def HelloSubOrchestrator(context):
39
+ return "Hello" + context
40
+
41
+ def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
42
+ return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
43
+
44
+
45
+ def add_hello_suborch_action(state: OrchestratorState, input_: str):
46
+ action = CallSubOrchestratorAction(function_name='HelloSubOrchestrator', _input=input_)
47
+ state.actions.append([action])
48
+
49
+
50
+ def add_hello_suborch_completed_events(
51
+ context_builder: ContextBuilder, id_: int, result: str):
52
+ context_builder.add_sub_orchestrator_started_event(name="HelloSubOrchestrator", id_=id_,input_="")
53
+ context_builder.add_orchestrator_completed_event()
54
+ context_builder.add_orchestrator_started_event()
55
+ context_builder.add_sub_orchestrator_completed_event(result=result, id_=id_)
56
+
57
+ def test_tokyo_and_seattle_and_london_state():
58
+ context_builder = ContextBuilder('test_simple_function')
59
+ add_hello_suborch_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
60
+ add_hello_suborch_completed_events(context_builder, 1, "\"Hello Seattle!\"")
61
+ add_hello_suborch_completed_events(context_builder, 2, "\"Hello London!\"")
62
+
63
+ result = get_orchestration_state_result(
64
+ context_builder, generator_function)
65
+
66
+ expected_state = base_expected_state(
67
+ ['Hello Tokyo!', 'Hello Seattle!', 'Hello London!'])
68
+ add_hello_suborch_action(expected_state, 'Tokyo')
69
+ add_hello_suborch_action(expected_state, 'Seattle')
70
+ add_hello_suborch_action(expected_state, 'London')
71
+ expected_state._is_done = True
72
+ expected = expected_state.to_json()
73
+
74
+ #assert_valid_schema(result)
75
+ assert_orchestration_state_equals(expected, result)
76
+
77
+ def test_call_suborchestrator_by_name():
78
+ context_builder = ContextBuilder('test_call_suborchestrator_by_name')
79
+ add_hello_suborch_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
80
+ add_hello_suborch_completed_events(context_builder, 1, "\"Hello Seattle!\"")
81
+ add_hello_suborch_completed_events(context_builder, 2, "\"Hello London!\"")
82
+
83
+ result = get_orchestration_state_result(
84
+ context_builder, generator_function_call_by_function_name)
85
+
86
+ expected_state = base_expected_state(
87
+ ['Hello Tokyo!', 'Hello Seattle!', 'Hello London!'])
88
+ add_hello_suborch_action(expected_state, 'Tokyo')
89
+ add_hello_suborch_action(expected_state, 'Seattle')
90
+ add_hello_suborch_action(expected_state, 'London')
91
+ expected_state._is_done = True
92
+ expected = expected_state.to_json()
93
+
94
+ #assert_valid_schema(result)
95
+ assert_orchestration_state_equals(expected, result)
@@ -1,130 +1,130 @@
1
- from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
- from .orchestrator_test_utils \
3
- import assert_orchestration_state_equals, get_orchestration_state_result, assert_valid_schema
4
- from tests.test_utils.ContextBuilder import ContextBuilder
5
- from azure.durable_functions.models.OrchestratorState import OrchestratorState
6
- from azure.durable_functions.models.RetryOptions import RetryOptions
7
- from azure.durable_functions.models.actions.CallSubOrchestratorWithRetryAction \
8
- import CallSubOrchestratorWithRetryAction
9
-
10
- RETRY_OPTIONS = RetryOptions(5000, 3)
11
-
12
- def generator_function(context):
13
- outputs = []
14
- retry_options = RETRY_OPTIONS
15
-
16
- task1 = yield context.call_sub_orchestrator_with_retry("HelloSubOrchestrator", retry_options, "Tokyo")
17
- task2 = yield context.call_sub_orchestrator_with_retry("HelloSubOrchestrator", retry_options, "Seattle")
18
- task3 = yield context.call_sub_orchestrator_with_retry("HelloSubOrchestrator", retry_options, "London")
19
-
20
- outputs.append(task1)
21
- outputs.append(task2)
22
- outputs.append(task3)
23
-
24
- return outputs
25
-
26
- def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
27
- return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
28
-
29
-
30
- def add_hello_suborch_action(state: OrchestratorState, input_: str):
31
- retry_options = RETRY_OPTIONS
32
- action = CallSubOrchestratorWithRetryAction(function_name='HelloSubOrchestrator',
33
- retry_options=retry_options,_input=input_)
34
- state.actions.append([action])
35
-
36
-
37
- def add_hello_suborch_completed_events(
38
- context_builder: ContextBuilder, id_: int, result: str):
39
- context_builder.add_sub_orchestrator_started_event(name="HelloSubOrchestrator", id_=id_,input_="")
40
- context_builder.add_orchestrator_completed_event()
41
- context_builder.add_orchestrator_started_event()
42
- context_builder.add_sub_orchestrator_completed_event(result=result, id_=id_)
43
-
44
- def add_hello_suborch_failed_events(
45
- context_builder: ContextBuilder, id_: int, reason: str, details: str):
46
- context_builder.add_sub_orchestrator_started_event(name="HelloSubOrchestrator", id_=id_,input_="")
47
- context_builder.add_orchestrator_completed_event()
48
- context_builder.add_orchestrator_started_event()
49
- context_builder.add_sub_orchestrator_failed_event(id_=id_, reason=reason, details=details)
50
-
51
- def add_retry_timer_events(context_builder: ContextBuilder, id_: int):
52
- fire_at = context_builder.add_timer_created_event(id_)
53
- context_builder.add_orchestrator_completed_event()
54
- context_builder.add_orchestrator_started_event()
55
- context_builder.add_timer_fired_event(id_=id_, fire_at=fire_at)
56
-
57
- def test_tokyo_and_seattle_and_london_state():
58
- context_builder = ContextBuilder('test_simple_function')
59
- add_hello_suborch_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
60
- add_hello_suborch_completed_events(context_builder, 1, "\"Hello Seattle!\"")
61
- add_hello_suborch_completed_events(context_builder, 2, "\"Hello London!\"")
62
-
63
- result = get_orchestration_state_result(
64
- context_builder, generator_function)
65
-
66
- expected_state = base_expected_state(
67
- ['Hello Tokyo!', 'Hello Seattle!', 'Hello London!'])
68
- add_hello_suborch_action(expected_state, 'Tokyo')
69
- add_hello_suborch_action(expected_state, 'Seattle')
70
- add_hello_suborch_action(expected_state, 'London')
71
- expected_state._is_done = True
72
- expected = expected_state.to_json()
73
-
74
- #assert_valid_schema(result)
75
- assert_orchestration_state_equals(expected, result)
76
-
77
-
78
- def test_tokyo_and_seattle_and_london_state_partial_failure():
79
- failed_reason = 'Reasons'
80
- failed_details = 'Stuff and Things'
81
- context_builder = ContextBuilder('test_simple_function')
82
- add_hello_suborch_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
83
- add_hello_suborch_failed_events(context_builder, 1, failed_reason, failed_details)
84
- add_retry_timer_events(context_builder, 2)
85
- add_hello_suborch_completed_events(context_builder, 3, "\"Hello Seattle!\"")
86
- add_hello_suborch_completed_events(context_builder, 4, "\"Hello London!\"")
87
-
88
- result = get_orchestration_state_result(
89
- context_builder, generator_function)
90
-
91
- expected_state = base_expected_state(
92
- ['Hello Tokyo!', 'Hello Seattle!', 'Hello London!'])
93
- add_hello_suborch_action(expected_state, 'Tokyo')
94
- add_hello_suborch_action(expected_state, 'Seattle')
95
- add_hello_suborch_action(expected_state, 'London')
96
- expected_state._is_done = True
97
- expected = expected_state.to_json()
98
-
99
- #assert_valid_schema(result)
100
- assert_orchestration_state_equals(expected, result)
101
-
102
- def test_tokyo_and_seattle_and_london_state_all_failed():
103
- failed_reason = 'Reasons'
104
- failed_details = 'Stuff and Things'
105
- context_builder = ContextBuilder('test_simple_function')
106
- add_hello_suborch_failed_events(context_builder, 0, failed_reason, failed_details)
107
- add_retry_timer_events(context_builder, 1)
108
- add_hello_suborch_failed_events(context_builder, 2, failed_reason, failed_details)
109
- add_retry_timer_events(context_builder, 3)
110
- add_hello_suborch_failed_events(context_builder, 4, failed_reason, failed_details)
111
- add_retry_timer_events(context_builder, 5)
112
-
113
- try:
114
- result = get_orchestration_state_result(
115
- context_builder, generator_function)
116
- # Should have error'ed out
117
- assert False
118
- except Exception as e:
119
- error_label = "\n\n$OutOfProcData$:"
120
- error_str = str(e)
121
-
122
- expected_state = base_expected_state()
123
- add_hello_suborch_action(expected_state, 'Tokyo')
124
-
125
- error_msg = f'{failed_reason} \n {failed_details}'
126
- expected_state._error = error_msg
127
- state_str = expected_state.to_json_string()
128
-
129
- expected_error_str = f"{error_msg}{error_label}{state_str}"
1
+ from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
+ from .orchestrator_test_utils \
3
+ import assert_orchestration_state_equals, get_orchestration_state_result, assert_valid_schema
4
+ from tests.test_utils.ContextBuilder import ContextBuilder
5
+ from azure.durable_functions.models.OrchestratorState import OrchestratorState
6
+ from azure.durable_functions.models.RetryOptions import RetryOptions
7
+ from azure.durable_functions.models.actions.CallSubOrchestratorWithRetryAction \
8
+ import CallSubOrchestratorWithRetryAction
9
+
10
+ RETRY_OPTIONS = RetryOptions(5000, 3)
11
+
12
+ def generator_function(context):
13
+ outputs = []
14
+ retry_options = RETRY_OPTIONS
15
+
16
+ task1 = yield context.call_sub_orchestrator_with_retry("HelloSubOrchestrator", retry_options, "Tokyo")
17
+ task2 = yield context.call_sub_orchestrator_with_retry("HelloSubOrchestrator", retry_options, "Seattle")
18
+ task3 = yield context.call_sub_orchestrator_with_retry("HelloSubOrchestrator", retry_options, "London")
19
+
20
+ outputs.append(task1)
21
+ outputs.append(task2)
22
+ outputs.append(task3)
23
+
24
+ return outputs
25
+
26
+ def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
27
+ return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
28
+
29
+
30
+ def add_hello_suborch_action(state: OrchestratorState, input_: str):
31
+ retry_options = RETRY_OPTIONS
32
+ action = CallSubOrchestratorWithRetryAction(function_name='HelloSubOrchestrator',
33
+ retry_options=retry_options,_input=input_)
34
+ state.actions.append([action])
35
+
36
+
37
+ def add_hello_suborch_completed_events(
38
+ context_builder: ContextBuilder, id_: int, result: str):
39
+ context_builder.add_sub_orchestrator_started_event(name="HelloSubOrchestrator", id_=id_,input_="")
40
+ context_builder.add_orchestrator_completed_event()
41
+ context_builder.add_orchestrator_started_event()
42
+ context_builder.add_sub_orchestrator_completed_event(result=result, id_=id_)
43
+
44
+ def add_hello_suborch_failed_events(
45
+ context_builder: ContextBuilder, id_: int, reason: str, details: str):
46
+ context_builder.add_sub_orchestrator_started_event(name="HelloSubOrchestrator", id_=id_,input_="")
47
+ context_builder.add_orchestrator_completed_event()
48
+ context_builder.add_orchestrator_started_event()
49
+ context_builder.add_sub_orchestrator_failed_event(id_=id_, reason=reason, details=details)
50
+
51
+ def add_retry_timer_events(context_builder: ContextBuilder, id_: int):
52
+ fire_at = context_builder.add_timer_created_event(id_)
53
+ context_builder.add_orchestrator_completed_event()
54
+ context_builder.add_orchestrator_started_event()
55
+ context_builder.add_timer_fired_event(id_=id_, fire_at=fire_at)
56
+
57
+ def test_tokyo_and_seattle_and_london_state():
58
+ context_builder = ContextBuilder('test_simple_function')
59
+ add_hello_suborch_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
60
+ add_hello_suborch_completed_events(context_builder, 1, "\"Hello Seattle!\"")
61
+ add_hello_suborch_completed_events(context_builder, 2, "\"Hello London!\"")
62
+
63
+ result = get_orchestration_state_result(
64
+ context_builder, generator_function)
65
+
66
+ expected_state = base_expected_state(
67
+ ['Hello Tokyo!', 'Hello Seattle!', 'Hello London!'])
68
+ add_hello_suborch_action(expected_state, 'Tokyo')
69
+ add_hello_suborch_action(expected_state, 'Seattle')
70
+ add_hello_suborch_action(expected_state, 'London')
71
+ expected_state._is_done = True
72
+ expected = expected_state.to_json()
73
+
74
+ #assert_valid_schema(result)
75
+ assert_orchestration_state_equals(expected, result)
76
+
77
+
78
+ def test_tokyo_and_seattle_and_london_state_partial_failure():
79
+ failed_reason = 'Reasons'
80
+ failed_details = 'Stuff and Things'
81
+ context_builder = ContextBuilder('test_simple_function')
82
+ add_hello_suborch_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
83
+ add_hello_suborch_failed_events(context_builder, 1, failed_reason, failed_details)
84
+ add_retry_timer_events(context_builder, 2)
85
+ add_hello_suborch_completed_events(context_builder, 3, "\"Hello Seattle!\"")
86
+ add_hello_suborch_completed_events(context_builder, 4, "\"Hello London!\"")
87
+
88
+ result = get_orchestration_state_result(
89
+ context_builder, generator_function)
90
+
91
+ expected_state = base_expected_state(
92
+ ['Hello Tokyo!', 'Hello Seattle!', 'Hello London!'])
93
+ add_hello_suborch_action(expected_state, 'Tokyo')
94
+ add_hello_suborch_action(expected_state, 'Seattle')
95
+ add_hello_suborch_action(expected_state, 'London')
96
+ expected_state._is_done = True
97
+ expected = expected_state.to_json()
98
+
99
+ #assert_valid_schema(result)
100
+ assert_orchestration_state_equals(expected, result)
101
+
102
+ def test_tokyo_and_seattle_and_london_state_all_failed():
103
+ failed_reason = 'Reasons'
104
+ failed_details = 'Stuff and Things'
105
+ context_builder = ContextBuilder('test_simple_function')
106
+ add_hello_suborch_failed_events(context_builder, 0, failed_reason, failed_details)
107
+ add_retry_timer_events(context_builder, 1)
108
+ add_hello_suborch_failed_events(context_builder, 2, failed_reason, failed_details)
109
+ add_retry_timer_events(context_builder, 3)
110
+ add_hello_suborch_failed_events(context_builder, 4, failed_reason, failed_details)
111
+ add_retry_timer_events(context_builder, 5)
112
+
113
+ try:
114
+ result = get_orchestration_state_result(
115
+ context_builder, generator_function)
116
+ # Should have error'ed out
117
+ assert False
118
+ except Exception as e:
119
+ error_label = "\n\n$OutOfProcData$:"
120
+ error_str = str(e)
121
+
122
+ expected_state = base_expected_state()
123
+ add_hello_suborch_action(expected_state, 'Tokyo')
124
+
125
+ error_msg = f'{failed_reason} \n {failed_details}'
126
+ expected_state._error = error_msg
127
+ state_str = expected_state.to_json_string()
128
+
129
+ expected_error_str = f"{error_msg}{error_label}{state_str}"
130
130
  assert expected_error_str == error_str
@@ -1,61 +1,61 @@
1
- from tests.orchestrator.test_fan_out_fan_in import add_completed_event, add_failed_event, base_expected_state, add_multi_actions
2
- from tests.orchestrator.orchestrator_test_utils import assert_orchestration_state_equals, get_orchestration_state_result
3
- from tests.test_utils.ContextBuilder import ContextBuilder
4
-
5
- def generator_function(context):
6
- task1 = context.call_activity("Hello", "0")
7
- task2 = context.call_activity("Hello", "1")
8
- task3 = context.call_activity("Hello", "2")
9
- task4 = context.task_any([task1, task2, task3])
10
- first_completed_task = yield task4
11
- try:
12
- result = yield first_completed_task
13
- return result
14
- except:
15
- return "exception"
16
-
17
- def generator_function_no_activity(context):
18
- yield context.task_any([])
19
- return "Done!"
20
-
21
- def test_continues_on_zero_inner_tasks():
22
- context_builder = ContextBuilder()
23
- result = get_orchestration_state_result(
24
- context_builder, generator_function_no_activity)
25
- expected_state = base_expected_state("Done!")
26
- expected_state._is_done = True
27
- expected = expected_state.to_json()
28
- assert_orchestration_state_equals(expected, result)
29
-
30
- def test_continues_on_zero_results():
31
- context_builder = ContextBuilder()
32
- result = get_orchestration_state_result(
33
- context_builder, generator_function)
34
- expected_state = base_expected_state()
35
- add_multi_actions(expected_state, function_name='Hello', volume=3)
36
- expected = expected_state.to_json()
37
- assert_orchestration_state_equals(expected, result)
38
-
39
- def test_continues_on_one_failure():
40
- context_builder = ContextBuilder()
41
- add_failed_event(context_builder, 0, "Hello", reason="", details="")
42
- result = get_orchestration_state_result(
43
- context_builder, generator_function)
44
- add_failed_event(context_builder, 0, "Hello", reason="", details="")
45
- expected_state = base_expected_state("exception")
46
- add_multi_actions(expected_state, function_name='Hello', volume=3)
47
- expected_state._is_done = True
48
- expected = expected_state.to_json()
49
- assert_orchestration_state_equals(expected, result)
50
-
51
- def test_succeeds_on_one_result():
52
- context_builder = ContextBuilder()
53
- add_completed_event(context_builder, 0, "Hello", result="1")
54
- result = get_orchestration_state_result(
55
- context_builder, generator_function)
56
- add_completed_event(context_builder, 2, "Hello", "3")
57
- expected_state = base_expected_state("1")
58
- add_multi_actions(expected_state, function_name='Hello', volume=3)
59
- expected_state._is_done = True
60
- expected = expected_state.to_json()
1
+ from tests.orchestrator.test_fan_out_fan_in import add_completed_event, add_failed_event, base_expected_state, add_multi_actions
2
+ from tests.orchestrator.orchestrator_test_utils import assert_orchestration_state_equals, get_orchestration_state_result
3
+ from tests.test_utils.ContextBuilder import ContextBuilder
4
+
5
+ def generator_function(context):
6
+ task1 = context.call_activity("Hello", "0")
7
+ task2 = context.call_activity("Hello", "1")
8
+ task3 = context.call_activity("Hello", "2")
9
+ task4 = context.task_any([task1, task2, task3])
10
+ first_completed_task = yield task4
11
+ try:
12
+ result = yield first_completed_task
13
+ return result
14
+ except:
15
+ return "exception"
16
+
17
+ def generator_function_no_activity(context):
18
+ yield context.task_any([])
19
+ return "Done!"
20
+
21
+ def test_continues_on_zero_inner_tasks():
22
+ context_builder = ContextBuilder()
23
+ result = get_orchestration_state_result(
24
+ context_builder, generator_function_no_activity)
25
+ expected_state = base_expected_state("Done!")
26
+ expected_state._is_done = True
27
+ expected = expected_state.to_json()
28
+ assert_orchestration_state_equals(expected, result)
29
+
30
+ def test_continues_on_zero_results():
31
+ context_builder = ContextBuilder()
32
+ result = get_orchestration_state_result(
33
+ context_builder, generator_function)
34
+ expected_state = base_expected_state()
35
+ add_multi_actions(expected_state, function_name='Hello', volume=3)
36
+ expected = expected_state.to_json()
37
+ assert_orchestration_state_equals(expected, result)
38
+
39
+ def test_continues_on_one_failure():
40
+ context_builder = ContextBuilder()
41
+ add_failed_event(context_builder, 0, "Hello", reason="", details="")
42
+ result = get_orchestration_state_result(
43
+ context_builder, generator_function)
44
+ add_failed_event(context_builder, 0, "Hello", reason="", details="")
45
+ expected_state = base_expected_state("exception")
46
+ add_multi_actions(expected_state, function_name='Hello', volume=3)
47
+ expected_state._is_done = True
48
+ expected = expected_state.to_json()
49
+ assert_orchestration_state_equals(expected, result)
50
+
51
+ def test_succeeds_on_one_result():
52
+ context_builder = ContextBuilder()
53
+ add_completed_event(context_builder, 0, "Hello", result="1")
54
+ result = get_orchestration_state_result(
55
+ context_builder, generator_function)
56
+ add_completed_event(context_builder, 2, "Hello", "3")
57
+ expected_state = base_expected_state("1")
58
+ add_multi_actions(expected_state, function_name='Hello', volume=3)
59
+ expected_state._is_done = True
60
+ expected = expected_state.to_json()
61
61
  assert_orchestration_state_equals(expected, result)