Skip to content

Commit 45a8911

Browse files
authored
Reporting non-existent orchestrations in start_new (#142)
1 parent 74f218a commit 45a8911

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

azure/durable_functions/models/DurableOrchestrationClient.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,16 @@ async def start_new(self,
7373

7474
if response[0] <= 202 and response[1]:
7575
return response[1]["id"]
76+
elif response[0] == 400:
77+
# Orchestrator not found, report clean exception
78+
exception_data = response[1]
79+
exception_message = exception_data["ExceptionMessage"]
80+
raise Exception(exception_message)
7681
else:
77-
return None
82+
# Catch all: simply surfacing the durable-extension exception
83+
# we surface the stack trace too, since this may be a more involed exception
84+
exception_message = response[1]
85+
raise Exception(exception_message)
7886

7987
def create_check_status_response(self, request, instance_id):
8088
"""Create a HttpResponse that contains useful information for \

tests/models/test_DurableOrchestrationClient.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
MESSAGE_500 = 'instance failed with unhandled exception'
2020
MESSAGE_501 = "well we didn't expect that"
2121

22+
TEST_ORCHESTRATOR = "MyDurableOrchestrator"
23+
EXCEPTION_ORCHESTRATOR_NOT_FOUND_EXMESSAGE = "The function <orchestrator> doesn't exist,"\
24+
" is disabled, or is not an orchestrator function. Additional info: "\
25+
"the following are the known orchestrator functions: <list>"
26+
EXCEPTION_ORCHESTRATOR_NOT_FOUND_MESSAGE = "One or more of the arguments submitted is incorrect"
27+
EXCEPTION_TYPE_ORCHESTRATOR_NOT_FOUND = "System.ArgumentException"
28+
STACK_TRACE = "' at Microsoft.Azure.WebJobs.Extensions.DurableTask..."
2229

2330
class MockRequest:
2431
def __init__(self, expected_url: str, response: [int, any]):
@@ -497,3 +504,39 @@ async def test_wait_or_response_check_status_response(binding_string):
497504
with pytest.raises(Exception):
498505
await client.wait_for_completion_or_create_check_status_response(
499506
None, TEST_INSTANCE_ID, timeout_in_milliseconds=500)
507+
508+
@pytest.mark.asyncio
509+
async def test_start_new_orchestrator_not_found(binding_string):
510+
"""Test that we throw the right exception when the orchestrator is not found.
511+
"""
512+
status = dict(ExceptionMessage=EXCEPTION_ORCHESTRATOR_NOT_FOUND_EXMESSAGE,
513+
StackTrace=STACK_TRACE,
514+
Message=EXCEPTION_ORCHESTRATOR_NOT_FOUND_MESSAGE,
515+
ExceptionType=EXCEPTION_TYPE_ORCHESTRATOR_NOT_FOUND)
516+
mock_request = MockRequest(expected_url=f"{RPC_BASE_URL}orchestrators/{TEST_ORCHESTRATOR}",
517+
response=[400, status])
518+
client = DurableOrchestrationClient(binding_string)
519+
client._post_async_request = mock_request.post
520+
521+
with pytest.raises(Exception) as ex:
522+
await client.start_new(TEST_ORCHESTRATOR)
523+
ex.match(EXCEPTION_ORCHESTRATOR_NOT_FOUND_EXMESSAGE)
524+
525+
526+
@pytest.mark.asyncio
527+
async def test_start_new_orchestrator_internal_exception(binding_string):
528+
"""Test that we throw the right exception when the extension fails internally.
529+
"""
530+
status = dict(ExceptionMessage=EXCEPTION_ORCHESTRATOR_NOT_FOUND_EXMESSAGE,
531+
StackTrace=STACK_TRACE,
532+
Message=EXCEPTION_ORCHESTRATOR_NOT_FOUND_MESSAGE,
533+
ExceptionType=EXCEPTION_TYPE_ORCHESTRATOR_NOT_FOUND)
534+
mock_request = MockRequest(expected_url=f"{RPC_BASE_URL}orchestrators/{TEST_ORCHESTRATOR}",
535+
response=[500, status])
536+
client = DurableOrchestrationClient(binding_string)
537+
client._post_async_request = mock_request.post
538+
539+
status_str = str(status)
540+
with pytest.raises(Exception) as ex:
541+
await client.start_new(TEST_ORCHESTRATOR)
542+
ex.match(status_str)

0 commit comments

Comments
 (0)