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
Notice the `yield context.task_all(tasks);` line. All the individual calls to the `E2_CopyFileToBlob` function were *not* yielded, which allows them to run in parallel. When we pass this array of tasks to `context.task_all`, we get back a task that won't complete *until all the copy operations have completed*. If you're familiar with [`asyncio.gather`](https://docs.python.org/3/library/asyncio-task.html#asyncio.gather) in Python, 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.
100
-
101
-
> [!NOTE]
102
-
> Although tasks are conceptually similar to Python awaitables, orchestrator functions should use `yield` as well as the `context.task_all` and `context.task_any` APIs to manage task parallelization.
103
-
104
-
After yielding from `context.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 we can calculate the sum total byte count by adding all the return values together.
105
-
106
-
---
107
-
108
89
### Helper activity functions
109
90
110
91
The helper activity functions, as with other samples, are just regular functions that use the `activityTrigger` trigger binding.
@@ -137,16 +118,6 @@ And here is the implementation:
The Python implementation uses the [Azure Storage SDK for Python](https://github.com/Azure/azure-storage-python) to upload the files to Azure Blob Storage.
The implementation loads the file from disk and asynchronously streams the contents into a blob of the same name in the "backups" container. The return value is the number of bytes copied to storage, that is then used by the orchestrator function to compute the aggregate sum.
> It may not be obvious at first, but this orchestrator does not violate the [deterministic orchestration constraint](durable-functions-code-constraints.md). It is deterministic because the `currentUtcDateTime` property is used to calculate the timer expiration time, and it returns the same value on every replay at this point in the orchestrator code. This behavior is important to ensure that the same `winner` results from every repeated call to `context.df.Task.any`.
74
-
>
75
-
> # [Python (V2)](#tab/python-v2)
76
-
77
-
The **E4_SmsPhoneVerification** function uses the standard *function.json* for orchestrator functions.
> It may not be obvious at first, but this orchestrator does not violate the [deterministic orchestration constraint](durable-functions-code-constraints.md). It is deterministic because the `currentUtcDateTime` property is used to calculate the timer expiration time, and it returns the same value on every replay at this point in the orchestrator code. This behavior is important to ensure that the same `winner` results from every repeated call to `context.df.Task.any`.
87
74
@@ -130,17 +117,6 @@ And here is the code that generates the four-digit challenge code and sends the
Copy file name to clipboardExpand all lines: articles/azure-functions/durable/durable-functions-sequence.md
+4-55Lines changed: 4 additions & 55 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -64,6 +64,10 @@ The `context` object contains a `df` durable orchestration context object that l
64
64
65
65
# [Python](#tab/python)
66
66
67
+
> [!NOTE]
68
+
> Python Durable Functions are available for the Functions 3.0 runtime only.
69
+
70
+
67
71
#### function.json
68
72
69
73
If you use Visual Studio Code or the Azure portal for development, here's the content of the *function.json* file for the orchestrator function. Most orchestrator *function.json* files look almost exactly like this.
@@ -88,28 +92,6 @@ All Python orchestration functions must include the [`durable-functions` package
88
92
89
93
The `context` object lets you call other *activity* functions and pass input parameters using its `call_activity` method. The code calls `E1_SayHello` three times in sequence with different parameter values, using `yield` to indicate the execution should wait on the async activity function calls to be returned. The return value of each call is returned at the end of the function.
> To abide by the "no I/O" rule of orchestrator functions, don't use any input or output bindings when using the `orchestrationTrigger` trigger binding. If other input or output bindings are needed, they should instead be used in the context of `activityTrigger` functions, which are called by the orchestrator. For more information, see the [orchestrator function code constraints](durable-functions-code-constraints.md) article.
All Python orchestration functions must include the [`durable-functions` package](https://pypi.org/project/azure-functions-durable). It's a library that enables you to write Durable Functions in Python. There are two significant differences between an orchestrator function and other Python functions:
107
-
108
-
1. The orchestrator function is a [generator function](https://wiki.python.org/moin/Generators).
109
-
2. The _file_ should register the orchestrator function as an orchestrator by stating `main = df.Orchestrator.create(<orchestrator function name>)` at the end of the file. This helps distinguish it from other, helper, functions declared in the file.
110
-
111
-
The `context` object lets you call other *activity* functions and pass input parameters using its `call_activity` method. The code calls `E1_SayHello` three times in sequence with different parameter values, using `yield` to indicate the execution should wait on the async activity function calls to be returned. The return value of each call is returned at the end of the function.
112
-
113
95
---
114
96
115
97
## E1_SayHello activity function
@@ -164,25 +146,6 @@ The implementation of `E1_SayHello` is a relatively trivial string formatting op
164
146
165
147
Unlike the orchestrator function, an activity function needs no special setup. The input passed to it by the orchestrator function is directly accessible as the parameter to the function.
166
148
167
-
# [Python (V2)](#tab/python-v2)
168
-
169
-
#### E1_SayHello/function.json
170
-
171
-
The *function.json* file for the activity function `E1_SayHello` is similar to that of `E1_HelloSequence` except that it uses an `activityTrigger` binding type instead of an `orchestrationTrigger` binding type.
Unlike the orchestrator function, an activity function needs no special setup. The input passed to it by the orchestrator function is directly accessible as the parameter to the function.
185
-
186
149
---
187
150
188
151
## HttpStart client function
@@ -223,20 +186,6 @@ To interact with orchestrators, the function must include a `durableClient` inpu
223
186
224
187
Use the `DurableOrchestrationClient` constructor to obtain a Durable Functions client. You use the client to start an orchestration. It can also help you return an HTTP response containing URLs for checking the status of the new orchestration.
Use the `DurableOrchestrationClient` constructor to obtain a Durable Functions client. You use the client to start an orchestration. It can also help you return an HTTP response containing URLs for checking the status of the new orchestration.
0 commit comments