v1.0.0
New
- Add CHANGELOG.md file to track changes across versions
Updates
- Updated
DataConverterExceptionwith detail error message (#78) - Updated
OrchestratorBlockedEventandTaskFailedExceptionto be unchecked exceptions (#88) - update dependency azure-functions-java-library to 2.2.0 - include azure-functions-java-spi as
compileOnlydependency (#95)
Breaking changes
- Use java worker middleware to avoid wrapper method when create orchestrator function (#87)
- Fixed
DurableClientContext.createCheckStatusResponseto return 202 (#92) - context.allOf() throws
CompositeTaskFailedException(RuntimeException)when one or more tasks fail instead ofRuntimeException(#54) - Updated
DurableTaskClient.purgeInstances(...)to take a timeout parameter and throwTimeoutException(#37) - The
waitForInstanceStart(...)andwaitForInstanceCompletion(...)methods of theDurableTaskClientinterface now throw a checkedTimeoutException
Code pattern updates
Before version 1.0.0, the orchestrator function needs to be wrapped by a OrchestrationRunner.loadAndRun wrapper function, accept a String parameter, and return a String result, as below:
/**
* This is the orchestrator function. The OrchestrationRunner.loadAndRun() static
* method is used to take the function input and execute the orchestrator logic.
*/
@FunctionName("Cities")
public String citiesOrchestrator(
@DurableOrchestrationTrigger(name = "orchestratorRequestProtoBytes") String orchestratorRequestProtoBytes) {
return OrchestrationRunner.loadAndRun(orchestratorRequestProtoBytes, ctx -> {
String result = "";
result += ctx.callActivity("Capitalize", "Tokyo", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "London", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "Seattle", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "Austin", String.class).await();
return result;
});
}From version 1.0.0, the orchestrator function doesn't need the wrapper function anymore. Instead, it takes a TaskOrchestrationContext parameter directly and can return any serializable return value, as below:
/**
* This is the orchestrator function. The OrchestrationRunner.loadAndRun() static
* method is used to take the function input and execute the orchestrator logic.
*/
@FunctionName("Cities")
public String citiesOrchestrator(
@DurableOrchestrationTrigger(name = "taskOrchestrationContext") TaskOrchestrationContext ctx) {
String result = "";
result += ctx.callActivity("Capitalize", "Tokyo", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "London", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "Seattle", String.class).await() + ", ";
result += ctx.callActivity("Capitalize", "Austin", String.class).await();
return result;
}This change makes the process of writing orchestrator functions simpler more consistent with the rest of the Azure Functions experience.
If you don't change your orchestrator function code and leave in the OrchestrationRunner.loadAndRun(...) wrapper, the execution of the orchestrator function to fail instantly with an error that looks like the following:
[2022-12-06T21:19:49.172Z] Dec 06, 2022 1:19:49 PM com.microsoft.durabletask.TaskOrchestrationExecutor execute
[2022-12-06T21:19:49.172Z] WARNING: The orchestrator failed with an unhandled exception: java.lang.RuntimeException: Unexpected failure in the task execution
This happens because the wrapper call is now redundant. This logic has been abstracted away in Durable Functions-specific middleware and calling it a second time in your function code will fail due to an unexpected input format.