durable-task-dotnet

Durable Task .NET SDK with Durable Task Scheduler

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "durable-task-dotnet" with this command: npx skills add azure-samples/durable-task-scheduler/azure-samples-durable-task-scheduler-durable-task-dotnet

Durable Task .NET SDK with Durable Task Scheduler

Build fault-tolerant, stateful workflows in .NET applications using the Durable Task SDK connected to Azure Durable Task Scheduler.

Quick Start

Required NuGet Packages

<ItemGroup> <PackageReference Include="Microsoft.DurableTask.Client.AzureManaged" Version="1." /> <PackageReference Include="Microsoft.DurableTask.Worker.AzureManaged" Version="1." /> <PackageReference Include="Microsoft.DurableTask.Generators" Version="1." OutputItemType="Analyzer" /> <PackageReference Include="Azure.Identity" Version="1." /> <PackageReference Include="Grpc.Net.Client" Version="2.*" /> </ItemGroup>

Minimal Worker Setup

using Microsoft.DurableTask; using Microsoft.DurableTask.Worker; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);

// Connection string format: "Endpoint={url};TaskHub={name};Authentication={type}" var connectionString = Environment.GetEnvironmentVariable("DURABLE_TASK_SCHEDULER_CONNECTION_STRING") ?? "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None";

builder.Services.AddDurableTaskWorker() .AddTasks(registry => { registry.AddAllGeneratedTasks(); // Registers all [DurableTask] decorated classes }) .UseDurableTaskScheduler(connectionString);

var host = builder.Build(); await host.RunAsync();

Minimal Client Setup

using Microsoft.DurableTask.Client;

var connectionString = Environment.GetEnvironmentVariable("DURABLE_TASK_SCHEDULER_CONNECTION_STRING") ?? "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None";

var client = DurableTaskClientBuilder.UseDurableTaskScheduler(connectionString).Build();

// Schedule an orchestration string instanceId = await client.ScheduleNewOrchestrationInstanceAsync("MyOrchestration", input);

// Wait for completion var result = await client.WaitForInstanceCompletionAsync(instanceId, getInputsAndOutputs: true);

Pattern Selection Guide

Pattern Use When

Function Chaining Sequential steps where each depends on the previous

Fan-Out/Fan-In Parallel processing with aggregated results

Human Interaction Workflow pauses for external input/approval

Durable Entities Stateful objects with operations (counters, accounts)

Sub-Orchestrations Reusable workflow components or version isolation

See references/patterns.md for detailed implementations.

Orchestration Structure

Basic Orchestration

[DurableTask(nameof(MyOrchestration))] public class MyOrchestration : TaskOrchestrator<string, string> { public override async Task<string> RunAsync(TaskOrchestrationContext context, string input) { // Call activities var result1 = await context.CallActivityAsync<string>(nameof(Step1Activity), input); var result2 = await context.CallActivityAsync<string>(nameof(Step2Activity), result1); return result2; } }

Basic Activity

[DurableTask(nameof(MyActivity))] public class MyActivity : TaskActivity<string, string> { private readonly ILogger<MyActivity> _logger;

public MyActivity(ILoggerFactory loggerFactory)
{
    _logger = loggerFactory.CreateLogger&#x3C;MyActivity>();
}

public override Task&#x3C;string> RunAsync(TaskActivityContext context, string input)
{
    _logger.LogInformation("Processing: {Input}", input);
    return Task.FromResult($"Processed: {input}");
}

}

Critical Rules

Orchestration Determinism

Orchestrations replay from history - all code MUST be deterministic:

NEVER do inside orchestrations:

  • DateTime.Now , DateTime.UtcNow → Use context.CurrentUtcDateTime

  • Guid.NewGuid() → Use context.NewGuid()

  • Random → Pass random values from activities

  • Direct I/O, HTTP calls, database access → Move to activities

  • Task.Delay() → Use context.CreateTimer()

  • Non-deterministic LINQ (parallel, unordered)

ALWAYS safe:

  • context.CallActivityAsync<T>()

  • context.CallSubOrchestrationAsync<T>()

  • context.CreateTimer()

  • context.WaitForExternalEvent<T>()

  • context.CurrentUtcDateTime

  • context.NewGuid()

  • context.SetCustomStatus()

Error Handling

public override async Task<string> RunAsync(TaskOrchestrationContext context, string input) { try { return await context.CallActivityAsync<string>(nameof(RiskyActivity), input); } catch (TaskFailedException ex) { // Activity failed - implement compensation or retry context.SetCustomStatus(new { Error = ex.Message }); return await context.CallActivityAsync<string>(nameof(CompensationActivity), input); } }

Retry Policies

var options = new TaskOptions { Retry = new RetryPolicy( maxNumberOfAttempts: 3, firstRetryInterval: TimeSpan.FromSeconds(5), backoffCoefficient: 2.0, maxRetryInterval: TimeSpan.FromMinutes(1)) };

await context.CallActivityAsync<string>(nameof(UnreliableActivity), input, options);

Connection & Authentication

Connection String Formats

// Local emulator (no auth) "Endpoint=http://localhost:8080;TaskHub=default;Authentication=None"

// Azure with DefaultAzureCredential "Endpoint=https://my-scheduler.region.durabletask.io;TaskHub=my-hub;Authentication=DefaultAzure"

// Azure with Managed Identity "Endpoint=https://my-scheduler.region.durabletask.io;TaskHub=my-hub;Authentication=ManagedIdentity"

// Azure with specific credential "Endpoint=https://my-scheduler.region.durabletask.io;TaskHub=my-hub;Authentication=AzureCLI"

Authentication Helper

static string GetConnectionString() { var endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? "http://localhost:8080"; var taskHub = Environment.GetEnvironmentVariable("TASKHUB") ?? "default";

var authType = endpoint.StartsWith("http://localhost") ? "None" : "DefaultAzure";
return $"Endpoint={endpoint};TaskHub={taskHub};Authentication={authType}";

}

Local Development with Emulator

Pull and run the emulator

docker pull mcr.microsoft.com/dts/dts-emulator:latest docker run -d -p 8080:8080 -p 8082:8082 --name dts-emulator mcr.microsoft.com/dts/dts-emulator:latest

Dashboard available at http://localhost:8082

References

  • patterns.md - Detailed pattern implementations (Fan-Out/Fan-In, Human Interaction, Entities, Sub-Orchestrations)

  • setup.md - Azure Durable Task Scheduler provisioning and deployment

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

durable-functions-dotnet

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

durable-task-java

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

durable-task-python

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

github-pr-inline-reply

No summary provided by upstream source.

Repository SourceNeeds Review