You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: articles/azure-functions/durable/durable-functions-cloud-backup.md
+36-4Lines changed: 36 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,14 +2,19 @@
2
2
title: Fan-out/fan-in scenarios in Durable Functions - Azure
3
3
description: Learn how to implement a fan-out-fan-in scenario in the Durable Functions extension for Azure Functions.
4
4
ms.topic: conceptual
5
-
ms.date: 11/02/2019
5
+
ms.date: 02/14/2023
6
6
ms.author: azfuncdf
7
7
---
8
8
9
9
# Fan-out/fan-in scenario in Durable Functions - Cloud backup example
10
10
11
11
*Fan-out/fan-in* refers to the pattern of executing multiple functions concurrently and then performing some aggregation on the results. This article explains a sample that uses [Durable Functions](durable-functions-overview.md) to implement a fan-in/fan-out scenario. The sample is a durable function that backs up all or some of an app's site content into Azure Storage.
12
12
13
+
> [!NOTE]
14
+
> The new programming model for authoring Functions in Node.js (V4) is currently in preview. Compared to the current model, the new experience is designed to be more idiomatic and intuitive for JavaScript and TypeScript developers. To learn more, see the Azure Functions Node.js [developer guide](../functions-reference-node.md?pivots=nodejs-model-v4).
15
+
>
16
+
> In the following code snippets, JavaScript (PM4) denotes programming model V4, the new experience.
@@ -50,7 +55,7 @@ Notice the `await Task.WhenAll(tasks);` line. All the individual calls to the `E
50
55
51
56
After awaiting from `Task.WhenAll`, we know that all function calls have completed and have returned values back to us. Each call to `E2_CopyFileToBlob` returns the number of bytes uploaded, so calculating the sum total byte count is a matter of adding all those return values together.
52
57
53
-
# [JavaScript](#tab/javascript)
58
+
# [JavaScript (PM3)](#tab/javascript-v3)
54
59
55
60
The function uses the standard *function.json* for orchestrator functions.
56
61
@@ -67,6 +72,19 @@ Notice the `yield context.df.Task.all(tasks);` line. All the individual calls to
67
72
68
73
After yielding from `context.df.Task.all`, we know that all function calls have completed and have returned values back to us. Each call to `E2_CopyFileToBlob` returns the number of bytes uploaded, so calculating the sum total byte count is a matter of adding all those return values together.
69
74
75
+
# [JavaScript (PM4)](#tab/javascript-v4)
76
+
77
+
Here is the code that implements the orchestrator function:
Notice the `yield context.df.Task.all(tasks);` line. All the individual calls to the `copyFileToBlob` function were *not* yielded, which allows them to run in parallel. When we pass this array of tasks to `context.df.Task.all`, we get back a task that won't complete *until all the copy operations have completed*. If you're familiar with [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) in JavaScript, then this is not new to you. 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.
82
+
83
+
> [!NOTE]
84
+
> Although Tasks are conceptually similar to JavaScript promises, orchestrator functions should use `context.df.Task.all` and `context.df.Task.any` instead of `Promise.all` and `Promise.race` to manage task parallelization.
85
+
86
+
After yielding from `context.df.Task.all`, we know that all function calls have completed and have returned values back to us. Each call to `copyFileToBlob` returns the number of bytes uploaded, so calculating the sum total byte count is a matter of adding all those return values together.
87
+
70
88
# [Python](#tab/python)
71
89
72
90
The function uses the standard *function.json* for orchestrator functions.
@@ -96,7 +114,7 @@ The helper activity functions, as with other samples, are just regular functions
The function uses the `readdirp` module (version `3.x`) to recursively read the directory structure.
136
+
111
137
# [Python](#tab/python)
112
138
113
139
The *function.json* file for `E2_GetFileList` looks like the following:
@@ -134,7 +160,7 @@ And here is the implementation:
134
160
135
161
The function uses some advanced features of Azure Functions bindings (that is, the use of the [`Binder` parameter](../functions-dotnet-class-library.md#binding-at-runtime)), but you don't need to worry about those details for the purpose of this walkthrough.
136
162
137
-
# [JavaScript](#tab/javascript)
163
+
# [JavaScript (PM3)](#tab/javascript-v3)
138
164
139
165
The *function.json* file for `E2_CopyFileToBlob` is similarly simple:
140
166
@@ -144,6 +170,12 @@ The JavaScript implementation uses the [Azure Storage SDK for Node](https://gith
Durable Function orchestrations are implemented in code and can use the programming language's built-in error-handling features. There really aren't any new concepts you need to learn to add error handling and compensation into your orchestrations. However, there are a few behaviors that you should be aware of.
13
13
14
+
> [!NOTE]
15
+
> The new programming model for authoring Functions in Node.js (V4) is currently in preview. Compared to the current model, the new experience is designed to be more idiomatic and intuitive for JavaScript and TypeScript developers. To learn more, see the Azure Functions Node.js [developer guide](../functions-reference-node.md?pivots=nodejs-model-v4).
16
+
>
17
+
> In the following code snippets, JavaScript (PM4) denotes programming model V4, the new experience.
18
+
14
19
## Errors in activity functions
15
20
16
21
Any exception that is thrown in an activity function is marshaled back to the orchestrator function and thrown as a `FunctionFailedException`. You can write error handling and compensation code that suits your needs in the orchestrator function.
@@ -95,41 +100,63 @@ public static async Task Run(
JavaScript doesn't currently support custom retry handlers. However, you still have the option of implementing retry logic directly in the orchestrator function using loops, exception handling, and timers for injecting delays between retries.
422
+
423
+
# [JavaScript (PM4)](#tab/javascript-v4)
376
424
377
425
JavaScript doesn't currently support custom retry handlers. However, you still have the option of implementing retry logic directly in the orchestrator function using loops, exception handling, and timers for injecting delays between retries.
378
426
@@ -474,7 +522,7 @@ public static async Task<bool> Run([OrchestrationTrigger] TaskOrchestrationConte
0 commit comments