The Durable Task .NET SDK is a standalone .NET library for implementing Durable Task orchestrations, activities, and entities. It's specifically designed to connect to a "sidecar" process, such as the Azure Functions .NET Isolated host, or a managed Azure endpoint, such as the Durable Task Scheduler (preview).
This project is different from the Durable Task Framework, which supports running fully self-hosted apps using a storage-based backend like Azure Storage or MSSQL.
The following nuget packages are available for download.
Name | Latest version | Description |
---|---|---|
Azure Functions Extension | For Durable Functions in .NET isolated. | |
Abstractions SDK | Contains base abstractions for Durable. Useful for writing re-usable libraries independent of the chosen worker or client. | |
Client SDK | Contains the core client logic for interacting with a Durable backend. | |
Client.Grpc SDK | The gRPC client implementation. | |
Client.AzureManaged SDK | The client implementation for use with the Durable Task Scheduler (preview). | |
Worker SDK | Contains the core worker logic for having a IHostedService to process durable tasks. |
|
Worker.Grpc SDK | The gRPC worker implementation. | |
Worker.AzureManaged SDK | The worker implementation for use with the Durable Task Scheduler (preview). | |
Source Generators | Source generators for type-safe orchestration and activity invocations. |
This SDK can be used to build Durable Functions apps that run in the Azure Functions .NET Isolated worker process.
To get started, add the Microsoft.Azure.Functions.Worker.Extensions.DurableTask nuget package to your Function app project. Make sure you're using the latest .NET Worker SDK packages.
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.10.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.2.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.7.0" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.DurableTask.Generators" Version="1.0.0-preview.1" OutputItemType="Analyzer" />
</ItemGroup>
You can then use the following code to define a simple "Hello, cities" durable orchestration, triggered by an HTTP request.
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;
using Microsoft.Extensions.Logging;
namespace IsolatedFunctionApp1.Untyped;
static class HelloSequenceUntyped
{
[Function(nameof(StartHelloCitiesUntyped))]
public static async Task<HttpResponseData> StartHelloCitiesUntyped(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client,
FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger(nameof(StartHelloCitiesUntyped));
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(nameof(HelloCitiesUntyped));
logger.LogInformation("Created new orchestration with instance ID = {instanceId}", instanceId);
return client.CreateCheckStatusResponse(req, instanceId);
}
[Function(nameof(HelloCitiesUntyped))]
public static async Task<string> HelloCitiesUntyped([OrchestrationTrigger] TaskOrchestrationContext context)
{
string result = "";
result += await context.CallActivityAsync<string>(nameof(SayHelloUntyped), "Tokyo") + " ";
result += await context.CallActivityAsync<string>(nameof(SayHelloUntyped), "London") + " ";
result += await context.CallActivityAsync<string>(nameof(SayHelloUntyped), "Seattle");
return result;
}
[Function(nameof(SayHelloUntyped))]
public static string SayHelloUntyped([ActivityTrigger] string cityName, FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger(nameof(SayHelloUntyped));
logger.LogInformation("Saying hello to {name}", cityName);
return $"Hello, {cityName}!";
}
}
You can find the full sample file, including detailed comments, at samples/AzureFunctionsApp/HelloCitiesUntyped.cs.
IMPORTANT: class based syntax in Durable Functions relies on a package reference to Microsoft.DurableTask.Generators
. This is still in "preview" and may be subject to significant change before 1.0 or even post-1.0. It is recommended to stick with function-syntax for now.
A new feature in this version of Durable Functions for .NET Isolated is the ability to define orchestrators and activities as classes instead of as functions. When using the class-based syntax, source generators are used to generate function definitions behind the scenes to instantiate and invoke your classes.
The source generators also generate type-safe extension methods on the client
and context
objects, removing the need to reference other activities or orchestrations by name, or to use type parameters to declare the return type. The following sample demonstrates the same "Hello cities!" orchestration using the class-based syntax and source-generated extension methods.
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;
using Microsoft.Extensions.Logging;
namespace IsolatedFunctionApp1.Typed;
public static class HelloCitiesTypedStarter
{
[Function(nameof(StartHelloCitiesTyped))]
public static async Task<HttpResponseData> StartHelloCitiesTyped(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client,
FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger(nameof(StartHelloCitiesTyped));
string instanceId = await client.ScheduleNewHelloCitiesTypedInstanceAsync();
logger.LogInformation("Created new orchestration with instance ID = {instanceId}", instanceId);
return client.CreateCheckStatusResponse(req, instanceId);
}
}
[DurableTask(nameof(HelloCitiesTyped))]
public class HelloCitiesTyped : TaskOrchestrator<string?, string>
{
public async override Task<string> RunAsync(TaskOrchestrationContext context, string? input)
{
string result = "";
result += await context.CallSayHelloTypedAsync("Tokyo") + " ";
result += await context.CallSayHelloTypedAsync("London") + " ";
result += await context.CallSayHelloTypedAsync("Seattle");
return result;
}
}
[DurableTask(nameof(SayHelloTyped))]
public class SayHelloTyped : TaskActivity<string, string>
{
readonly ILogger? logger;
public SayHelloTyped(ILoggerFactory? loggerFactory)
{
this.logger = loggerFactory?.CreateLogger<SayHelloTyped>();
}
public override Task<string> RunAsync(TaskActivityContext context, string cityName)
{
this.logger?.LogInformation("Saying hello to {name}", cityName);
return Task.FromResult($"Hello, {cityName}!");
}
}
You can find the full sample file, including detailed comments, at samples/AzureFunctionsApp/HelloCitiesTyped.cs.
This SDK is not compatible with Durable Functions for the .NET in-process worker. It only works with the newer out-of-process .NET Isolated worker.
The Durable Task Scheduler for Azure Functions is a managed backend that is currently in preview. Durable Functions apps can use the Durable Task Scheduler as one of its supported storage providers.
This SDK can also be used with the Durable Task Scheduler directly, without any Durable Functions dependency. To get started, sign up for the Durable Task Scheduler private preview and follow the instructions to create a new Durable Task Scheduler instance. Once granted access to the private preview GitHub repository, you can find samples and documentation for getting started here.
This project utilizes protobuf definitions from durabletask-protobuf, which are copied (vendored) into this repository under the src/Grpc
directory. See the corresponding README.md for more information about how to update the protobuf definitions.
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.