Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion azure/durable_functions/models/DurableOrchestrationClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,16 @@ async def start_new(self,

if response[0] <= 202 and response[1]:
return response[1]["id"]
elif response[0] == 400:
# Orchestrator not found, report clean exception
exception_data = response[1]
exception_message = exception_data["ExceptionMessage"]
raise Exception(exception_message)
else:
return None
# Catch all: simply surfacing the durable-extension exception
# we surface the stack trace too, since this may be a more involed exception
exception_message = response[1]
raise Exception(exception_message)

def create_check_status_response(self, request, instance_id):
"""Create a HttpResponse that contains useful information for \
Expand Down
43 changes: 43 additions & 0 deletions tests/models/test_DurableOrchestrationClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
MESSAGE_500 = 'instance failed with unhandled exception'
MESSAGE_501 = "well we didn't expect that"

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

class MockRequest:
def __init__(self, expected_url: str, response: [int, any]):
Expand Down Expand Up @@ -497,3 +504,39 @@ async def test_wait_or_response_check_status_response(binding_string):
with pytest.raises(Exception):
await client.wait_for_completion_or_create_check_status_response(
None, TEST_INSTANCE_ID, timeout_in_milliseconds=500)

@pytest.mark.asyncio
async def test_start_new_orchestrator_not_found(binding_string):
"""Test that we throw the right exception when the orchestrator is not found.
"""
status = dict(ExceptionMessage=EXCEPTION_ORCHESTRATOR_NOT_FOUND_EXMESSAGE,
StackTrace=STACK_TRACE,
Message=EXCEPTION_ORCHESTRATOR_NOT_FOUND_MESSAGE,
ExceptionType=EXCEPTION_TYPE_ORCHESTRATOR_NOT_FOUND)
mock_request = MockRequest(expected_url=f"{RPC_BASE_URL}orchestrators/{TEST_ORCHESTRATOR}",
response=[400, status])
client = DurableOrchestrationClient(binding_string)
client._post_async_request = mock_request.post

with pytest.raises(Exception) as ex:
await client.start_new(TEST_ORCHESTRATOR)
ex.match(EXCEPTION_ORCHESTRATOR_NOT_FOUND_EXMESSAGE)


@pytest.mark.asyncio
async def test_start_new_orchestrator_internal_exception(binding_string):
"""Test that we throw the right exception when the extension fails internally.
"""
status = dict(ExceptionMessage=EXCEPTION_ORCHESTRATOR_NOT_FOUND_EXMESSAGE,
StackTrace=STACK_TRACE,
Message=EXCEPTION_ORCHESTRATOR_NOT_FOUND_MESSAGE,
ExceptionType=EXCEPTION_TYPE_ORCHESTRATOR_NOT_FOUND)
mock_request = MockRequest(expected_url=f"{RPC_BASE_URL}orchestrators/{TEST_ORCHESTRATOR}",
response=[500, status])
client = DurableOrchestrationClient(binding_string)
client._post_async_request = mock_request.post

status_str = str(status)
with pytest.raises(Exception) as ex:
await client.start_new(TEST_ORCHESTRATOR)
ex.match(status_str)