-
Notifications
You must be signed in to change notification settings - Fork 92
Add Durable Task Scheduler skill #919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
40a54a9
Add Durable Task Scheduler skill
greenie-msft 28d208e
Update DTS skill to include RBAC guidance and SKU guidance
greenie-msft 44c659e
Add DTS to architecture guidance table for workflow
greenie-msft 7ee8a8e
Address PR #919 feedback: fix auth levels, capitalization, and Bicep …
greenie-msft 5029f1d
Move DTS deployment content to azure-deploy skill
greenie-msft 86216ff
Pin NuGet package versions to latest stable
greenie-msft 9f0ae81
Update plugin/skills/azure-prepare/references/services/durable-task-s…
greenie-msft b69b461
Fix link checker failures
greenie-msft a98054c
Add DTS to research.md service mapping to fix orphan check
greenie-msft ab371ec
Update plugin/skills/azure-prepare/references/research.md
greenie-msft 8c8d03e
Address Copilot review: fix plan.md ref, add Bicep params, align UAMI…
greenie-msft 61fcec3
Restructure DTS as directory with per-language sub-files
greenie-msft 4ce7a98
Fix link checker: replace cross-skill link in bicep.md with text refe…
greenie-msft 3ce0c82
Address Copilot review: standardize host.json, fix snippets
greenie-msft be1b711
Update plugin/skills/azure-prepare/references/research.md
paulyuk 34955c3
Move Learn More to top, standardize env vars across all files
greenie-msft 4f730c4
fix: capitalize DTS SKU names in Bicep examples (Consumption/Dedicated)
greenie-msft 7e25a86
feat: add DTS dashboard RBAC for deploying user
greenie-msft 4b62382
fix: address PR review comments
greenie-msft 60c0174
revert: remove DTS deploy recipe from azure-deploy skill
greenie-msft dc928d3
Add DTS integration tests and update routing to choose Durable Task S…
greenie-msft c57898a
Add DTS integration test for azure-prepare and azure-deploy. Address …
ba0ddfe
chore: bump azure-deploy to 1.0.4 and azure-prepare to 1.0.3
5f4cd17
fix: correct relative links to durable-task-scheduler folder
301d39f
fix: resolve remaining conflict markers in azure-deploy SKILL.md
a9cc058
docs: expand ACA/AKS abbreviations to full names in DTS references
88d9040
fix: add taskHubs to DTS Bicep resource requirement in SKILL.md routi…
greenie-msft File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
plugin/skills/azure-prepare/references/services/durable-task-scheduler/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| # Durable Task Scheduler | ||
|
|
||
| Build reliable, fault-tolerant workflows using durable execution with Azure Durable Task Scheduler. | ||
|
|
||
| ## When to Use | ||
|
|
||
| - Long-running workflows requiring state persistence | ||
| - Distributed transactions with compensating actions (saga pattern) | ||
| - Multi-step orchestrations with checkpointing | ||
| - Fan-out/fan-in parallel processing | ||
| - Workflows requiring human interaction or external events | ||
| - Stateful entities (aggregators, counters, state machines) | ||
| - Multi-agent AI orchestration | ||
| - Data processing pipelines | ||
|
|
||
| ## Framework Selection | ||
|
|
||
| | Framework | Best For | Hosting | | ||
| |-----------|----------|---------| | ||
| | **Durable Functions** | Serverless event-driven apps | Azure Functions | | ||
| | **Durable Task SDKs** | Any compute (containers, VMs) | Azure Container Apps, Azure Kubernetes Service, App Service, VMs | | ||
|
|
||
| > **💡 TIP**: Use Durable Functions for serverless with built-in triggers. Use Durable Task SDKs for hosting flexibility. | ||
|
|
||
| ## Quick Start - Local Emulator | ||
|
|
||
| ```bash | ||
| # Start the emulator (see https://mcr.microsoft.com/v2/dts/dts-emulator/tags/list for available versions) | ||
| 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 | ||
| ``` | ||
|
|
||
| ## Workflow Patterns | ||
|
|
||
| | Pattern | Use When | | ||
| |---------|----------| | ||
| | **Function Chaining** | Sequential steps, each depends on previous | | ||
| | **Fan-Out/Fan-In** | Parallel processing with aggregated results | | ||
| | **Async HTTP APIs** | Long-running operations with HTTP polling | | ||
| | **Monitor** | Periodic polling with configurable timeouts | | ||
| | **Human Interaction** | Workflow pauses for external input/approval | | ||
| | **Saga** | Distributed transactions with compensation | | ||
| | **Durable Entities** | Stateful objects (counters, accounts) | | ||
|
|
||
| ## Connection & Authentication | ||
|
|
||
| | Environment | Connection String | | ||
| |-------------|-------------------| | ||
| | Local Development (Emulator) | `Endpoint=http://localhost:8080;Authentication=None;TaskHub=default` | | ||
| | Azure (System-Assigned MI) | `Endpoint=https://<scheduler>.durabletask.io;Authentication=ManagedIdentity;TaskHub=default` | | ||
| | Azure (User-Assigned MI) | `Endpoint=https://<scheduler>.durabletask.io;Authentication=ManagedIdentity;ClientID=<uami-client-id>;TaskHub=default` | | ||
|
|
||
| > **⚠️ NOTE**: Durable Task Scheduler uses identity-based authentication only — no connection strings with keys. When using a User-Assigned Managed Identity (UAMI), you must include the `ClientID` in the connection string. | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| | Error | Cause | Fix | | ||
| |-------|-------|-----| | ||
| | **403 PermissionDenied** on gRPC call (e.g., `client.start_new()`) | Function App managed identity lacks RBAC on the Durable Task Scheduler resource, or IP allowlist blocks traffic | 1. Assign `Durable Task Data Contributor` role (`0ad04412-c4d5-4796-b79c-f76d14c8d402`) to the identity (SAMI or UAMI) scoped to the Durable Task Scheduler resource. For UAMI, also ensure the connection string includes `ClientID=<uami-client-id>`. 2. Ensure the scheduler's `ipAllowlist` includes `0.0.0.0/0` (an empty list denies all traffic). 3. RBAC propagation can take up to 10 minutes — restart the Function App after assigning roles. | | ||
| | **Connection refused** to emulator | Emulator container not running or wrong port | Verify container is running: `docker ps` and confirm port 8080 is mapped | | ||
| | **403 despite correct RBAC** | Scheduler IP allowlist is empty (denies all) | Set `ipAllowlist: ['0.0.0.0/0']` in Bicep or update via CLI: `az durabletask scheduler update --ip-allowlist '0.0.0.0/0'` | | ||
| | **TaskHub not found** | Task hub not provisioned or name mismatch | Ensure the `TaskHub` parameter in the `DURABLE_TASK_SCHEDULER_CONNECTION_STRING` matches the provisioned task hub name | | ||
| | **403 Forbidden** on DTS dashboard | Deploying user lacks RBAC on the scheduler | Assign `Durable Task Data Contributor` role to your own user identity (not just the Function App MI) scoped to the scheduler resource — see [Bicep Patterns](bicep.md) for the dashboard role assignment snippet | | ||
|
|
||
| ## References | ||
|
|
||
| - [.NET](dotnet.md) — packages, setup, examples, determinism, retry, SDK | ||
| - [Python](python.md) — packages, setup, examples, determinism, retry, SDK | ||
| - [Java](java.md) — dependencies, setup, examples, determinism, retry, SDK | ||
| - [JavaScript](javascript.md) — packages, setup, examples, determinism, retry, SDK | ||
| - [Bicep Patterns](bicep.md) — scheduler, task hub, RBAC, CLI provisioning | ||
| - [Official Documentation](https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/durable-task-scheduler) | ||
| - [Durable Functions Overview](https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-overview) | ||
| - [Sample Repository](https://github.com/Azure-Samples/Durable-Task-Scheduler) | ||
| - [Choosing an Orchestration Framework](https://learn.microsoft.com/azure/azure-functions/durable/durable-task-scheduler/choose-orchestration-framework) |
116 changes: 116 additions & 0 deletions
116
plugin/skills/azure-prepare/references/services/durable-task-scheduler/bicep.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| # Durable Task Scheduler — Bicep Patterns | ||
|
|
||
| Bicep templates for provisioning the Durable Task Scheduler, task hubs, and RBAC role assignments. | ||
|
|
||
| ## Scheduler + Task Hub | ||
|
|
||
| ```bicep | ||
| // Parameters — define these at file level or pass from a parent module | ||
| param schedulerName string | ||
| param location string = resourceGroup().location | ||
|
|
||
| @allowed(['Consumption', 'Dedicated']) | ||
| @description('Use Consumption for quickstarts/variable workloads, Dedicated for high-demand/predictable throughput') | ||
| param skuName string = 'Consumption' | ||
|
|
||
| resource scheduler 'Microsoft.DurableTask/schedulers@2025-11-01' = { | ||
| name: schedulerName | ||
| location: location | ||
| properties: { | ||
| sku: { name: skuName } | ||
| ipAllowlist: ['0.0.0.0/0'] // Required: empty list denies all traffic | ||
| } | ||
paulyuk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| resource taskHub 'Microsoft.DurableTask/schedulers/taskHubs@2025-11-01' = { | ||
| parent: scheduler | ||
| name: 'default' | ||
| } | ||
| ``` | ||
|
|
||
| ## SKU Selection | ||
|
|
||
| | SKU | Best For | | ||
| |-----|----------| | ||
| | **Consumption** | quickstarts, variable or bursty workloads, pay-per-use | | ||
| | **Dedicated** | High-demand workloads, predictable throughput requirements | | ||
|
|
||
| > **💡 TIP**: Start with `Consumption` for development and variable workloads. Switch to `Dedicated` when you need consistent, high-throughput performance. | ||
|
|
||
| > **⚠️ WARNING**: The scheduler's `ipAllowlist` **must** include at least one entry (e.g., `['0.0.0.0/0']` for allow-all). An empty array `[]` denies **all** traffic, causing 403 errors on gRPC calls even with correct RBAC. | ||
|
|
||
| ## RBAC — Durable Task Data Contributor | ||
|
|
||
| The Function App's managed identity **must** have the `Durable Task Data Contributor` role on the scheduler resource. Without it, the app receives **403 PermissionDenied** on gRPC calls. | ||
|
|
||
| ```bicep | ||
| // Assumes the UAMI principal ID is passed from the base template's identity module | ||
| param functionAppPrincipalId string | ||
|
|
||
| var durableTaskDataContributorRoleId = '0ad04412-c4d5-4796-b79c-f76d14c8d402' | ||
|
|
||
| resource durableTaskRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { | ||
| name: guid(scheduler.id, functionAppPrincipalId, durableTaskDataContributorRoleId) | ||
| scope: scheduler | ||
| properties: { | ||
| roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', durableTaskDataContributorRoleId) | ||
| principalId: functionAppPrincipalId | ||
| principalType: 'ServicePrincipal' | ||
| } | ||
greenie-msft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| ``` | ||
|
|
||
| ## RBAC — Dashboard Access for Developers | ||
|
|
||
| To allow developers to view orchestration status and history in the [DTS dashboard](https://portal.azure.com), assign the same `Durable Task Data Contributor` role to the deploying user's identity. Without this, the dashboard returns **403 Forbidden**. | ||
|
|
||
| ```bicep | ||
| // Accept the deploying user's principal ID (azd auto-populates this from AZURE_PRINCIPAL_ID) | ||
| param principalId string = '' | ||
|
|
||
| resource dashboardRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!empty(principalId)) { | ||
| name: guid(scheduler.id, principalId, durableTaskDataContributorRoleId) | ||
| scope: scheduler | ||
| properties: { | ||
| roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', durableTaskDataContributorRoleId) | ||
| principalId: principalId | ||
| principalType: 'User' | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| > **💡 TIP**: This is the same role used for the Function App's managed identity, but assigned with `principalType: 'User'` to the developer. See the [sample repo](https://github.com/Azure-Samples/Durable-Task-Scheduler/blob/main/samples/infra/main.bicep) for a full example. | ||
|
|
||
| ## Connection String App Setting | ||
|
|
||
| Include these entries in the Function App resource's `siteConfig.appSettings` array: | ||
|
|
||
| ```bicep | ||
| // UAMI client ID from base template identity module - REQUIRED for UAMI auth | ||
| param uamiClientId string | ||
|
|
||
| { | ||
| name: 'DURABLE_TASK_SCHEDULER_CONNECTION_STRING' | ||
| value: 'Endpoint=${scheduler.properties.endpoint};TaskHub=${taskHub.name};Authentication=ManagedIdentity;ClientID=${uamiClientId}' | ||
| } | ||
| ``` | ||
|
|
||
| > **⚠️ IMPORTANT**: The base templates use User Assigned Managed Identity (UAMI). You **must** include `ClientID=<uami-client-id>` in the connection string. Without it, the Durable Task SDK cannot resolve the correct identity. | ||
|
|
||
| > **⚠️ WARNING**: Always use `scheduler.properties.endpoint` to get the scheduler URL. Do **not** construct it manually — the endpoint includes a hash suffix and region (e.g., `https://myscheduler-abc123.westus2.durabletask.io`). | ||
|
|
||
| ## Provision via CLI | ||
|
|
||
| > **💡 TIP**: When hosting Durable Functions, use a **Flex Consumption** plan (`FC1` SKU) rather than the legacy Consumption plan (`Y1`). Flex Consumption supports identity-based storage connections natively and handles deployment artifacts correctly. | ||
|
|
||
| ```bash | ||
| # Install the durabletask CLI extension (if not already installed) | ||
| az extension add --name durabletask | ||
|
|
||
| # Create scheduler (consumption SKU for getting started) | ||
| az durabletask scheduler create \ | ||
| --resource-group myResourceGroup \ | ||
| --name my-scheduler \ | ||
| --location eastus \ | ||
| --sku consumption | ||
| ``` | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.