Skip to content

Commit 43568a9

Browse files
authored
Merge pull request #313401 from MicrosoftDocs/main
Auto Publish – main to live - 2026-03-19 17:00 UTC
2 parents b474df1 + a4f5800 commit 43568a9

41 files changed

Lines changed: 1085 additions & 86 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

articles/azure-functions/durable/durable-functions-error-handling.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ public static async Task Run(
8383
> - The exception message typically identifies which activity functions or sub-orchestrations caused the failure. To access more detailed error information, inspect the [`FailureDetails`](/dotnet/api/microsoft.durabletask.taskfailuredetails) property.
8484
> - By default, `FailureDetails` includes the **error type**, **error message**, **stack trace**, and any **nested inner exceptions** (each represented as a recursive `FailureDetails` object). To include additional exception properties in the failure output, see [Include Custom Exception Properties for FailureDetails (.NET Isolated)](#include-custom-exception-properties-for-failuredetails-net-isolated).
8585
86+
> [!IMPORTANT]
87+
> **Migration note (in-process to isolated):** In the in-process model, `FunctionFailedException.InnerException` contains the original exception object thrown by the activity, which you can cast and inspect directly. In the isolated worker model, `TaskFailedException` does **not** contain the original exception as an `InnerException`. Instead, error details are available only through the [`FailureDetails`](/dotnet/api/microsoft.durabletask.taskfailuredetails) property, which provides string-based properties (`ErrorType`, `ErrorMessage`, `StackTrace`). You can't cast or access the original exception object directly. Use [`FailureDetails.IsCausedBy<T>()`](/dotnet/api/microsoft.durabletask.taskfailuredetails.iscausedby) to check the original exception type.
88+
8689
</details>
8790
<br>
8891
<details>
@@ -438,6 +441,102 @@ If the **CreditAccount** activity fails, the orchestrator catches the exception
438441

439442
::: zone pivot="durable-functions"
440443

444+
## Errors with multiple activity calls (fan-out/fan-in)
445+
446+
# [C#](#tab/csharp)
447+
448+
When you use `Task.WhenAll` to run multiple activity calls in parallel (fan-out/fan-in pattern) and one or more activities fail, `await` throws only the first exception. To access all failures, inspect the `Exception` property on the `Task` returned by `Task.WhenAll`.
449+
450+
<details>
451+
<summary><b>Isolated worker model</b></summary>
452+
453+
```csharp
454+
var tasks = new[]
455+
{
456+
context.CallActivityAsync("Activity1", input1),
457+
context.CallActivityAsync("Activity2", input2),
458+
context.CallActivityAsync("Activity3", input3),
459+
};
460+
461+
var allTask = Task.WhenAll(tasks);
462+
try
463+
{
464+
await allTask;
465+
}
466+
catch (TaskFailedException)
467+
{
468+
// 'await' rethrows only the first exception. To inspect all failures,
469+
// check allTask.Exception, which is an AggregateException.
470+
if (allTask.Exception != null)
471+
{
472+
foreach (var inner in allTask.Exception.InnerExceptions)
473+
{
474+
if (inner is TaskFailedException taskFailed)
475+
{
476+
// Use taskFailed.FailureDetails to inspect error details
477+
var errorType = taskFailed.FailureDetails.ErrorType;
478+
var errorMessage = taskFailed.FailureDetails.ErrorMessage;
479+
}
480+
}
481+
}
482+
}
483+
```
484+
485+
</details>
486+
<br>
487+
<details>
488+
<summary><b>In-process model</b></summary>
489+
490+
```csharp
491+
var tasks = new[]
492+
{
493+
context.CallActivityAsync("Activity1", input1),
494+
context.CallActivityAsync("Activity2", input2),
495+
context.CallActivityAsync("Activity3", input3),
496+
};
497+
498+
var allTask = Task.WhenAll(tasks);
499+
try
500+
{
501+
await allTask;
502+
}
503+
catch (FunctionFailedException)
504+
{
505+
// 'await' rethrows only the first exception. To inspect all failures,
506+
// check allTask.Exception, which is an AggregateException.
507+
if (allTask.Exception != null)
508+
{
509+
foreach (var inner in allTask.Exception.InnerExceptions)
510+
{
511+
if (inner is FunctionFailedException funcFailed)
512+
{
513+
// Use funcFailed.InnerException to access the original exception
514+
}
515+
}
516+
}
517+
}
518+
```
519+
520+
</details>
521+
522+
# [JavaScript](#tab/javascript)
523+
524+
In JavaScript, when you use `context.df.Task.all` to run multiple activity calls in parallel, the first failure causes the task to complete with an error. Wrap the call in a try/catch block to handle the error.
525+
526+
# [Python](#tab/python)
527+
528+
In Python, when you use `context.task_all` to run multiple activity calls in parallel, the first failure causes the task to complete with an error. Wrap the call in a try/except block to handle the error.
529+
530+
# [PowerShell](#tab/powershell)
531+
532+
In PowerShell, use `Wait-DurableTask` with multiple tasks. If any task fails, the error is raised.
533+
534+
# [Java](#tab/java)
535+
536+
In Java, when you use `ctx.allOf` to run multiple activity calls in parallel, the first failure causes the task to complete with an error. Use a try/catch block to handle the error.
537+
538+
---
539+
441540
## Errors in entity functions
442541
Exception handling in entity functions depends on the Durable Functions hosting model:
443542

articles/azure-functions/durable/durable-functions-fan-in-fan-out.md

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,6 @@ This orchestrator function does the following:
9090

9191
Here is the code that implements the orchestrator function:
9292

93-
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/BackupSiteContent.cs?range=16-42)]
94-
95-
> [!NOTE]
96-
> The sample linked in the prerequisites (`samples/precompiled`) uses the in-process model. The following **Isolated model** sections show equivalent code for the .NET isolated worker model.
97-
98-
Notice the `await Task.WhenAll(tasks);` line. The code doesn't await the individual calls to `E2_CopyFileToBlob`, so they run in parallel. When the orchestrator passes the task array to `Task.WhenAll`, it returns a task that doesn't complete until all copy operations complete. If you're familiar with the Task Parallel Library (TPL) in .NET, this pattern is familiar. The difference is that these tasks could be running on multiple virtual machines concurrently, and the Durable Functions extension ensures that the end-to-end execution is resilient to process recycling.
99-
100-
After the orchestrator awaits `Task.WhenAll`, all function calls are complete and return values. Each call to `E2_CopyFileToBlob` returns the number of bytes uploaded. Calculate the total by adding the return values.
101-
102-
<br>
103-
10493
<details>
10594
<summary><b>Isolated model</b></summary>
10695

@@ -137,6 +126,22 @@ public static class BackupSiteContent
137126
}
138127
```
139128

129+
Notice the `await Task.WhenAll(tasks);` line. The code doesn't await the individual calls to `E2_CopyFileToBlob`, so they run in parallel. When the orchestrator passes the task array to `Task.WhenAll`, it returns a task that doesn't complete until all copy operations complete. If you're familiar with the Task Parallel Library (TPL) in .NET, this pattern is familiar. The difference is that these tasks could be running on multiple virtual machines concurrently, and the Durable Functions extension ensures that the end-to-end execution is resilient to process recycling.
130+
131+
After the orchestrator awaits `Task.WhenAll`, all function calls are complete and return values. Each call to `E2_CopyFileToBlob` returns the number of bytes uploaded. Calculate the total by adding the return values.
132+
133+
</details>
134+
135+
<br>
136+
137+
<details>
138+
<summary><b>In-process model</b></summary>
139+
140+
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/BackupSiteContent.cs?range=16-42)]
141+
142+
> [!NOTE]
143+
> The [in-process model sample](~/samples-durable-functions/samples/precompiled/BackupSiteContent.cs) uses deprecated in-process packages. The preceding code shows the recommended .NET isolated worker model.
144+
140145
</details>
141146

142147
<br>
@@ -364,10 +369,6 @@ The helper activity functions are regular functions that use the `activityTrigge
364369

365370
# [C#](#tab/csharp)
366371

367-
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/BackupSiteContent.cs?range=44-54)]
368-
369-
<br>
370-
371372
<details>
372373
<summary><b>Isolated model</b></summary>
373374

@@ -400,6 +401,15 @@ public static class BackupSiteContent
400401

401402
<br>
402403

404+
<details>
405+
<summary><b>In-process model</b></summary>
406+
407+
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/BackupSiteContent.cs?range=44-54)]
408+
409+
</details>
410+
411+
<br>
412+
403413
# [JavaScript](#tab/javascript)
404414

405415
<details>
@@ -457,18 +467,12 @@ Java sample coming soon.
457467

458468
# [C#](#tab/csharp)
459469

460-
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/BackupSiteContent.cs?range=56-81)]
461-
462-
> [!NOTE]
463-
> To run the sample code, install the `Microsoft.Azure.WebJobs.Extensions.Storage` NuGet package.
464-
465-
The function uses Azure Functions binding features like the [`Binder` parameter](../functions-dotnet-class-library.md#binding-at-runtime). You don't need those details for this walkthrough.
466-
467-
<br>
468-
469470
<details>
470471
<summary><b>Isolated model</b></summary>
471472

473+
> [!NOTE]
474+
> To run the sample code, install the `Azure.Storage.Blobs` NuGet package.
475+
472476
```csharp
473477
using System;
474478
using System.IO;
@@ -518,6 +522,18 @@ public static class BackupSiteContent
518522

519523
<br>
520524

525+
<details>
526+
<summary><b>In-process model</b></summary>
527+
528+
[!code-csharp[Main](~/samples-durable-functions/samples/precompiled/BackupSiteContent.cs?range=56-81)]
529+
530+
> [!NOTE]
531+
> The in-process model sample requires the `Microsoft.Azure.WebJobs.Extensions.Storage` NuGet package and uses Azure Functions binding features like the [`Binder` parameter](../functions-dotnet-class-library.md#binding-at-runtime).
532+
533+
</details>
534+
535+
<br>
536+
521537
# [JavaScript](#tab/javascript)
522538

523539
<details>

articles/azure-functions/durable/durable-functions-orchestrations.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ This article gives you an overview of orchestrator functions and how they can he
2424

2525
For information about the types of functions available in a Durable Functions app, see [Durable Task programming model](programming-model-overview.md).
2626

27+
> [!TIP]
28+
> If you use C# with the .NET isolated worker model, you can write orchestrations using either a **function-based** approach (static methods with `[Function]` attributes) or a **class-based** approach (classes that inherit from `TaskOrchestrator<TInput, TOutput>`). The class-based approach requires the [Microsoft.DurableTask.Generators](https://www.nuget.org/packages/Microsoft.DurableTask.Generators) source generator package and provides strongly typed invocations. For more information, see [Class-based activities and orchestrations](durable-functions-dotnet-isolated-overview.md#source-generator-and-class-based-activities-and-orchestrations). The C# code examples in this article show both approaches.
29+
2730
::: zone-end
2831

2932
::: zone pivot="durable-task-sdks"
@@ -116,6 +119,36 @@ public static async Task<List<string>> Run(
116119

117120
<br>
118121

122+
<details>
123+
<summary><b>Class-based model (isolated worker)</b></summary>
124+
125+
The class-based approach uses a source generator and requires the [Microsoft.DurableTask.Generators](https://www.nuget.org/packages/Microsoft.DurableTask.Generators) NuGet package.
126+
127+
```csharp
128+
using Microsoft.DurableTask;
129+
130+
[DurableTask]
131+
public class HelloCities : TaskOrchestrator<object?, List<string>>
132+
{
133+
public override async Task<List<string>> RunAsync(
134+
TaskOrchestrationContext context, object? input)
135+
{
136+
var outputs = new List<string>();
137+
138+
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
139+
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
140+
outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));
141+
142+
// Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
143+
return outputs;
144+
}
145+
}
146+
```
147+
148+
</details>
149+
150+
<br>
151+
119152
<details>
120153
<summary><b>In-process model</b></summary>
121154

articles/azure-functions/durable/durable-functions-singletons.md

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public static async Task<HttpResponseData> RunSingle(
6969
7070
# [JavaScript](#tab/javascript)
7171

72+
> [!NOTE]
73+
> This JavaScript example uses the Node.js programming model v3, which uses *function.json*. If you're using the Node.js programming model v4, use the v4 code-first pattern instead.
74+
7275
**function.json**
7376

7477
```json
@@ -130,57 +133,37 @@ module.exports = async function(context, req) {
130133

131134
# [Python](#tab/python)
132135

133-
**function.json**
134-
135-
```json
136-
{
137-
"bindings": [
138-
{
139-
"authLevel": "function",
140-
"name": "req",
141-
"type": "httpTrigger",
142-
"direction": "in",
143-
"route": "orchestrators/{functionName}/{instanceId}",
144-
"methods": ["post"]
145-
},
146-
{
147-
"name": "starter",
148-
"type": "orchestrationClient",
149-
"direction": "in"
150-
},
151-
{
152-
"name": "$return",
153-
"type": "http",
154-
"direction": "out"
155-
}
156-
]
157-
}
158-
```
159-
160-
**__init__.py**
136+
**function_app.py**
161137

162138
```python
163139
import logging
164140
import azure.functions as func
165141
import azure.durable_functions as df
166142

167-
async def main(req: func.HttpRequest, starter: str) -> func.HttpResponse:
168-
client = df.DurableOrchestrationClient(starter)
169-
instance_id = req.route_params['instanceId']
170-
function_name = req.route_params['functionName']
143+
app = df.DFApp(http_auth_level=func.AuthLevel.FUNCTION)
144+
145+
@app.route(route="orchestrators/{functionName}/{instanceId}", methods=["POST"])
146+
@app.durable_client_input(client_name="client")
147+
async def http_start_single(req: func.HttpRequest, client):
148+
instance_id = req.route_params["instanceId"]
149+
function_name = req.route_params["functionName"]
171150

172151
existing_instance = await client.get_status(instance_id)
173152

174-
if existing_instance.runtime_status in [df.OrchestrationRuntimeStatus.Completed, df.OrchestrationRuntimeStatus.Failed, df.OrchestrationRuntimeStatus.Terminated, None]:
153+
if not existing_instance or existing_instance.runtime_status in [
154+
df.OrchestrationRuntimeStatus.Completed,
155+
df.OrchestrationRuntimeStatus.Failed,
156+
df.OrchestrationRuntimeStatus.Terminated,
157+
]:
175158
event_data = req.get_body()
176-
instance_id = await client.start_new(function_name, instance_id, event_data)
159+
instance_id = await client.start_new(function_name, instance_id, event_data)
177160
logging.info(f"Started orchestration with ID = '{instance_id}'.")
178161
return client.create_check_status_response(req, instance_id)
179-
else:
180-
return {
181-
'status': 409,
182-
'body': f"An instance with ID '${existing_instance.instance_id}' already exists"
183-
}
162+
163+
return func.HttpResponse(
164+
body=f"An instance with ID '{instance_id}' already exists.",
165+
status_code=409,
166+
)
184167

185168
```
186169

articles/backup/azure-kubernetes-service-cluster-backup.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Back up Azure Kubernetes Service by using Azure Backup
33
description: Learn how to back up Azure Kubernetes Service (AKS) by using Azure Backup.
44
ms.topic: how-to
55
ms.service: azure-backup
6-
ms.date: 03/24/2025
6+
ms.date: 03/16/2026
77
author: AbhishekMallick-MS
88
ms.author: v-mallicka
99
# Customer intent: "As a DevOps engineer, I want to configure and manage Azure Backup for my AKS clusters so that I can ensure data protection and restore capabilities for my containerized applications."

0 commit comments

Comments
 (0)