azure-functions-durable 1.2.8__py3-none-any.whl → 1.2.10__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.
- azure/durable_functions/__init__.py +81 -81
- azure/durable_functions/constants.py +9 -9
- azure/durable_functions/decorators/__init__.py +3 -3
- azure/durable_functions/decorators/durable_app.py +249 -249
- azure/durable_functions/decorators/metadata.py +109 -109
- azure/durable_functions/entity.py +125 -125
- azure/durable_functions/models/DurableEntityContext.py +201 -201
- azure/durable_functions/models/DurableHttpRequest.py +58 -58
- azure/durable_functions/models/DurableOrchestrationBindings.py +66 -66
- azure/durable_functions/models/DurableOrchestrationClient.py +781 -711
- azure/durable_functions/models/DurableOrchestrationContext.py +722 -707
- azure/durable_functions/models/DurableOrchestrationStatus.py +156 -156
- azure/durable_functions/models/EntityStateResponse.py +23 -23
- azure/durable_functions/models/FunctionContext.py +7 -7
- azure/durable_functions/models/OrchestrationRuntimeStatus.py +32 -29
- azure/durable_functions/models/OrchestratorState.py +117 -116
- azure/durable_functions/models/PurgeHistoryResult.py +33 -33
- azure/durable_functions/models/ReplaySchema.py +8 -8
- azure/durable_functions/models/RetryOptions.py +69 -69
- azure/durable_functions/models/RpcManagementOptions.py +86 -86
- azure/durable_functions/models/Task.py +426 -426
- azure/durable_functions/models/TaskOrchestrationExecutor.py +346 -333
- azure/durable_functions/models/TokenSource.py +56 -56
- azure/durable_functions/models/__init__.py +24 -24
- azure/durable_functions/models/actions/Action.py +23 -23
- azure/durable_functions/models/actions/ActionType.py +18 -18
- azure/durable_functions/models/actions/CallActivityAction.py +41 -41
- azure/durable_functions/models/actions/CallActivityWithRetryAction.py +45 -45
- azure/durable_functions/models/actions/CallEntityAction.py +46 -46
- azure/durable_functions/models/actions/CallHttpAction.py +35 -35
- azure/durable_functions/models/actions/CallSubOrchestratorAction.py +40 -40
- azure/durable_functions/models/actions/CallSubOrchestratorWithRetryAction.py +44 -44
- azure/durable_functions/models/actions/CompoundAction.py +35 -35
- azure/durable_functions/models/actions/ContinueAsNewAction.py +36 -36
- azure/durable_functions/models/actions/CreateTimerAction.py +48 -48
- azure/durable_functions/models/actions/NoOpAction.py +35 -35
- azure/durable_functions/models/actions/SignalEntityAction.py +47 -47
- azure/durable_functions/models/actions/WaitForExternalEventAction.py +63 -63
- azure/durable_functions/models/actions/WhenAllAction.py +14 -14
- azure/durable_functions/models/actions/WhenAnyAction.py +14 -14
- azure/durable_functions/models/actions/__init__.py +24 -24
- azure/durable_functions/models/entities/EntityState.py +74 -74
- azure/durable_functions/models/entities/OperationResult.py +76 -76
- azure/durable_functions/models/entities/RequestMessage.py +53 -53
- azure/durable_functions/models/entities/ResponseMessage.py +48 -48
- azure/durable_functions/models/entities/Signal.py +62 -62
- azure/durable_functions/models/entities/__init__.py +17 -17
- azure/durable_functions/models/history/HistoryEvent.py +92 -92
- azure/durable_functions/models/history/HistoryEventType.py +27 -25
- azure/durable_functions/models/history/__init__.py +8 -8
- azure/durable_functions/models/utils/__init__.py +7 -7
- azure/durable_functions/models/utils/entity_utils.py +103 -91
- azure/durable_functions/models/utils/http_utils.py +69 -69
- azure/durable_functions/models/utils/json_utils.py +56 -56
- azure/durable_functions/orchestrator.py +71 -71
- {azure_functions_durable-1.2.8.dist-info → azure_functions_durable-1.2.10.dist-info}/LICENSE +21 -21
- {azure_functions_durable-1.2.8.dist-info → azure_functions_durable-1.2.10.dist-info}/METADATA +58 -58
- azure_functions_durable-1.2.10.dist-info/RECORD +100 -0
- {azure_functions_durable-1.2.8.dist-info → azure_functions_durable-1.2.10.dist-info}/WHEEL +1 -1
- tests/models/test_DecoratorMetadata.py +135 -135
- tests/models/test_Decorators.py +107 -107
- tests/models/test_DurableOrchestrationBindings.py +68 -56
- tests/models/test_DurableOrchestrationClient.py +730 -612
- tests/models/test_DurableOrchestrationContext.py +102 -102
- tests/models/test_DurableOrchestrationStatus.py +59 -59
- tests/models/test_OrchestrationState.py +28 -28
- tests/models/test_RpcManagementOptions.py +79 -79
- tests/models/test_TokenSource.py +10 -10
- tests/orchestrator/models/OrchestrationInstance.py +18 -18
- tests/orchestrator/orchestrator_test_utils.py +130 -130
- tests/orchestrator/schemas/OrchetrationStateSchema.py +66 -66
- tests/orchestrator/test_call_http.py +235 -176
- tests/orchestrator/test_continue_as_new.py +67 -67
- tests/orchestrator/test_create_timer.py +126 -126
- tests/orchestrator/test_entity.py +395 -395
- tests/orchestrator/test_external_event.py +53 -53
- tests/orchestrator/test_fan_out_fan_in.py +175 -175
- tests/orchestrator/test_is_replaying_flag.py +101 -101
- tests/orchestrator/test_retries.py +308 -308
- tests/orchestrator/test_sequential_orchestrator.py +841 -801
- tests/orchestrator/test_sequential_orchestrator_custom_status.py +119 -119
- tests/orchestrator/test_sequential_orchestrator_with_retry.py +465 -465
- tests/orchestrator/test_serialization.py +30 -30
- tests/orchestrator/test_sub_orchestrator.py +95 -95
- tests/orchestrator/test_sub_orchestrator_with_retry.py +129 -129
- tests/orchestrator/test_task_any.py +60 -60
- tests/tasks/tasks_test_utils.py +17 -17
- tests/tasks/test_new_uuid.py +34 -34
- tests/test_utils/ContextBuilder.py +174 -174
- tests/test_utils/EntityContextBuilder.py +56 -56
- tests/test_utils/constants.py +1 -1
- tests/test_utils/json_utils.py +30 -30
- tests/test_utils/testClasses.py +56 -56
- tests/utils/__init__.py +1 -0
- tests/utils/test_entity_utils.py +24 -0
- azure_functions_durable-1.2.8.data/data/_manifest/bsi.json +0 -1
- azure_functions_durable-1.2.8.data/data/_manifest/manifest.cat +0 -0
- azure_functions_durable-1.2.8.data/data/_manifest/manifest.spdx.json +0 -12845
- azure_functions_durable-1.2.8.data/data/_manifest/manifest.spdx.json.sha256 +0 -1
- azure_functions_durable-1.2.8.dist-info/RECORD +0 -102
- {azure_functions_durable-1.2.8.dist-info → azure_functions_durable-1.2.10.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)
|