Skip to content

Commit 61f81f2

Browse files
committed
Merge branch 'main' into release-aio-2603
2 parents d076a12 + f95e174 commit 61f81f2

60 files changed

Lines changed: 1316 additions & 216 deletions

File tree

Some content is hidden

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

articles/app-service/tutorial-nodejs-mongodb-app.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ ms.custom:
2525

2626
# Tutorial: Deploy a Node.js + MongoDB web app to Azure
2727

28-
This tutorial shows how to create a secure Node.js app in [Azure App Service](overview.md) that's connected to an [Azure Cosmos DB for MongoDB](/azure/cosmos-db/mongodb/mongodb-introduction) database. Azure App Service provides a highly scalable, self-patching web hosting service using the Linux operating system. When you're finished, you have an Express.js app running on Azure App Service on Linux.
28+
This tutorial shows how to create a secure Node.js app in [Azure App Service](overview.md) that's connected to an [Azure DocumentDB](https://learn.microsoft.com/azure/documentdb/) database. Azure App Service provides a highly scalable, self-patching web hosting service using the Linux operating system. When you're finished, you have an Express.js app running on Azure App Service on Linux.
2929

3030
:::image type="content" source="./media/tutorial-nodejs-mongodb-app/azure-portal-browse-app-2.png" alt-text="Screenshot of Node.js application storing data in Cosmos DB.":::
3131

@@ -125,7 +125,7 @@ Having issues? Check the [Troubleshooting section](#troubleshooting).
125125

126126
## Create App Service and Azure Cosmos DB
127127

128-
In this step, you create the Azure resources. The steps used in this tutorial create a set of secure-by-default resources that include App Service and Azure Cosmos DB for MongoDB. For the creation process, you specify:
128+
In this step, you create the Azure resources. The steps used in this tutorial create a set of secure-by-default resources that include App Service and Azure DocumentDB. For the creation process, you specify:
129129

130130
- The **Name** for the web app. It's part of the DNS name for your app.
131131
- The **Region** to run the app physically in the world. It's also part of the DNS name for your app.
@@ -171,7 +171,7 @@ Sign in to the [Azure portal](https://portal.azure.com/) and follow these steps
171171
- **Virtual network** → Integrated with the App Service app and isolates back-end network traffic.
172172
- **Private endpoint** → Access endpoint for the database resource in the virtual network.
173173
- **Network interface** → Represents a private IP address for the private endpoint.
174-
- **Azure Cosmos DB for MongoDB** → Accessible only from behind the private endpoint. A database and a user are created for you on the server.
174+
- **Azure DocumentDB** → Accessible only from behind the private endpoint. A database and a user are created for you on the server.
175175
- **Private DNS zone** → Enables DNS resolution of the Azure Cosmos DB server in the virtual network.
176176

177177
:::column-end:::
110 KB
Loading

articles/application-gateway/migrate-v1-v2.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,8 @@ For the legacy cloning script, version 1.0.11 is the new version of the migratio
385385
### Public IP retention script
386386
387387
After you successfully migrate the configuration and thoroughly test your new V2 gateway, this step focuses on redirecting live traffic.
388-
389-
We provide an Azure PowerShell script that *retains the public IP address from V1*. Here are important considerations for the script:
388+
> [!NOTE]
389+
> The IP migration script does not support public IP address resources that have name beginning with a numeric character.
390390
391391
- The script reserves the Basic public IP from V1, converts it to Standard, and attaches it to the V2 gateway. This action effectively redirects all incoming traffic to the V2 gateway.
392392
- This IP swap operation typically results in a brief *downtime of approximately one to five minutes*. Plan accordingly.

articles/application-gateway/tutorial-ingress-controller-add-on-new.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,27 @@ Deploying a new AKS cluster with the AGIC add-on enabled without specifying an e
5757
az aks create -n myCluster -g myResourceGroup --network-plugin azure --enable-managed-identity -a ingress-appgw --appgw-name myApplicationGateway --appgw-subnet-cidr "10.225.0.0/16" --generate-ssh-keys
5858
```
5959

60+
## Enable the add-on for the existing AKS cluster
61+
62+
You already have an existing AKS cluster and will enable the AGIC add-on. The add-on can be enabled either through the Azure portal or by using the Azure CLI.
63+
64+
# [Azure Portal](#tab/azure-portal)
65+
66+
In this page in the screenshot, you can create it simply by selecting the checkbox. If you want to specify a subnet prefix, select *Create new* and configure it manually.
67+
68+
:::image type="content" source="media/tutorial-ingress-controller-add-on-new/tutorial-ingress-controller-add-on-new.png" alt-text="Screenshot of enabling AGIC addon by Portal." lightbox="media/tutorial-ingress-controller-add-on-new/tutorial-ingress-controller-add-on-new.png":::
69+
70+
# [Azure CLI](#tab/azure-cli)
71+
72+
You can give the name of the application gateway as well as subnet CIDR by the command.
73+
appgw-subnet-cidr should be in the address prefixes in your virtual network. Please change *10.0.250.0/24* to your preferred application gateway subnet CIDR. This must always be within the address space range of your virtual network.
74+
75+
```azurecli
76+
$ az aks enable-addons --resource-group ${RG_NAME} --name ${CLUSTER_NAME} --addons ingress-appgw --appgw-subnet-cidr "10.0.250.0/24"
77+
```
78+
79+
In most cases, enabling the add-on automatically assigns the required permissions. However, depending on the environment, the permissions may not be granted automatically. In such cases, you should verify the permissions and assign them manually if necessary.
80+
6081
> [!NOTE]
6182
> Please ensure the identity used by AGIC has the proper permissions. A list of permissions needed by the identity can be found here: [Configure Infrastructure - Permissions](configuration-infrastructure.md#permissions). If a custom role is not defined with the required permissions, you may use the _Network Contributor_ role.
6283

articles/azure-functions/TOC.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@
270270
href: /security/benchmark/azure/baselines/functions-security-baseline?toc=/azure/azure-functions/toc.json&bc=/azure/azure-functions/breadcrumb/toc.json
271271
- name: Reliability
272272
items:
273-
- name: Availability zones and disaster recovery
273+
- name: Reliability in Azure Functions
274274
displayName: availability zones, high-availability, zone redundancy, disaster recovery
275275
href: /azure/reliability/reliability-functions?toc=/azure/azure-functions/toc.json&bc=/azure/azure-functions/breadcrumb/toc.json
276276
- name: Zone redundancy

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

Lines changed: 100 additions & 1 deletion
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

@@ -1229,7 +1328,7 @@ def orchestrator_function(context: df.DurableOrchestrationContext):
12291328
activity_task = context.call_activity('FlakyFunction')
12301329
timeout_task = context.create_timer(deadline)
12311330
1232-
winner = yield context.task_any(activity_task, timeout_task)
1331+
winner = yield context.task_any([activity_task, timeout_task])
12331332
if winner == activity_task:
12341333
timeout_task.cancel()
12351334
return True

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-http-features.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ public HttpResponseMessage httpStart(
194194

195195
---
196196

197+
> [!TIP]
198+
> If you have multiple HTTP-triggered starter functions in the same function app, configure a unique `route` for each function to avoid route conflicts. Using a parameterized route like `orchestrators/{functionName}` (as shown in several of the preceding examples) lets a single HTTP starter function start any orchestrator by name, which is often the simplest approach.
199+
197200
Starting an orchestrator function by using the HTTP-trigger functions shown previously can be done using any HTTP client. The following cURL command starts an orchestrator function named `DoWork`:
198201

199202
```bash

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

0 commit comments

Comments
 (0)