Skip to content

Commit 17ceeaa

Browse files
authored
Merge pull request #300624 from ggailey777/bundles
[Functions] Extension bundles support with refactoring
2 parents d02e2a8 + 3caf371 commit 17ceeaa

File tree

48 files changed

+229
-171
lines changed

Some content is hidden

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

48 files changed

+229
-171
lines changed

articles/azure-functions/TOC.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,8 @@
375375
href: functions-triggers-bindings.md
376376
- name: Register binding extensions
377377
href: functions-bindings-register.md
378-
displayName: bundles, extension bundles
378+
- name: Extension bundles
379+
href: extension-bundles.md
379380
- name: Binding expression patterns
380381
href: functions-bindings-expressions-patterns.md
381382
- name: Handle binding errors

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

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Make sure to choose your Durable Functions development language at the top of th
2121
2222
## Python v2 programming model
2323

24-
Durable Functions is supported in the new [Python v2 programming model](../functions-reference-python.md?pivots=python-mode-decorators). To use the v2 model, you must install the Durable Functions SDK, which is the PyPI package `azure-functions-durable`, version `1.2.2` or a later version. You must also check `host.json` to make sure your app is referencing [Extension Bundles](../functions-bindings-register.md#extension-bundles) version 4.x to use the v2 model with Durable Functions.
24+
Durable Functions is supported in the new [Python v2 programming model](../functions-reference-python.md?pivots=python-mode-decorators). To use the v2 model, you must install the Durable Functions SDK, which is the PyPI package `azure-functions-durable`, version `1.2.2` or a later version. You must also check `host.json` to make sure your app is referencing [Extension Bundles](../extension-bundles.md) version 4.x to use the v2 model with Durable Functions.
2525

2626
You can provide feedback and suggestions in the [Durable Functions SDK for Python repo](https://github.com/Azure/azure-functions-durable-python/issues).
2727
::: zone-end
@@ -53,12 +53,12 @@ When you write orchestrator functions, the orchestration trigger is defined by t
5353
::: zone pivot="programming-language-python"
5454
Azure Functions supports two programming models for Python. The way that you define an orchestration trigger depends on your chosen programming model.
5555

56-
# [v2](#tab/python-v2)
56+
### [v2](#tab/python-v2)
5757
The Python v2 programming model lets you define an orchestration trigger using the `orchestration_trigger` decorator directly in your Python function code.
5858

5959
In the v2 model, the Durable Functions triggers and bindings are accessed from an instance of `DFApp`, which is a subclass of `FunctionApp` that additionally exports Durable Functions-specific decorators.
6060

61-
# [v1](#tab/python-v1)
61+
### [v1](#tab/python-v1)
6262
When you write orchestrator functions in the Python v1 programming model, the orchestration trigger is defined by the following JSON object in the `bindings` array of the *function.json* file:
6363

6464
```json
@@ -82,7 +82,7 @@ Internally, this trigger binding polls the configured durable store for new orch
8282

8383
Here are some notes about the orchestration trigger:
8484

85-
* **Single-threading** - A single dispatcher thread is used for all orchestrator function execution on a single host instance. For this reason, it's important to ensure that orchestrator function code is efficient and doesn't perform any I/O. It is also important to ensure that this thread does not do any async work except when awaiting on Durable Functions-specific task types.
85+
* **Single-threading** - A single dispatcher thread is used for all orchestrator function execution on a single host instance. For this reason, it's important to ensure that orchestrator function code is efficient and doesn't perform any I/O. It's also important to ensure that this thread doesn't do any async work except when awaiting on Durable Functions-specific task types.
8686
* **Poison-message handling** - There's no poison message support in orchestration triggers.
8787
* **Message visibility** - Orchestration trigger messages are dequeued and kept invisible for a configurable duration. The visibility of these messages is renewed automatically as long as the function app is running and healthy.
8888
* **Return values** - Return values are serialized to JSON and persisted to the orchestration history table in Azure Table storage. These return values can be queried by the orchestration client binding, described later.
@@ -101,16 +101,16 @@ Here are some notes about the orchestration trigger:
101101
The orchestration trigger binding supports both inputs and outputs. Here are some things to know about input and output handling:
102102

103103
* **inputs** - Orchestration triggers can be invoked with inputs, which are accessed through the context input object. All inputs must be JSON-serializable.
104-
* **outputs** - Orchestration triggers support output values as well as inputs. The return value of the function is used to assign the output value and must be JSON-serializable.
104+
* **outputs** - Orchestration triggers support both output and input values. The return value of the function is used to assign the output value and must be JSON-serializable.
105105

106106
### Trigger sample
107107

108-
The following example code shows what the simplest "Hello World" orchestrator function might look like. Note that this example orchestrator doesn't actually schedule any tasks.
108+
The following example code shows what the simplest "Hello World" orchestrator function might look like. This example orchestrator doesn't actually schedule any tasks.
109109

110110
::: zone pivot="programming-language-csharp"
111-
The specific attribute used to define the trigger depends on whether you are running your C# functions [in-process](../functions-dotnet-class-library.md) or in an [isolated worker process](../dotnet-isolated-process-guide.md).
111+
The specific attribute used to define the trigger depends on whether you're running your C# functions [in-process](../functions-dotnet-class-library.md) or in an [isolated worker process](../dotnet-isolated-process-guide.md).
112112

113-
# [In-process](#tab/in-process)
113+
#### [In-process](#tab/in-process)
114114

115115
```csharp
116116
[FunctionName("HelloWorld")]
@@ -124,7 +124,7 @@ public static string Run([OrchestrationTrigger] IDurableOrchestrationContext con
124124
> [!NOTE]
125125
> The previous code is for Durable Functions 2.x. For Durable Functions 1.x, you must use `DurableOrchestrationContext` instead of `IDurableOrchestrationContext`. For more information about the differences between versions, see the [Durable Functions Versions](durable-functions-versions.md) article.
126126
127-
# [Isolated process](#tab/isolated-process)
127+
#### [Isolated process](#tab/isolated-process)
128128

129129
```csharp
130130
[Function("HelloWorld")]
@@ -135,7 +135,7 @@ public static string Run([OrchestrationTrigger] TaskOrchestrationContext context
135135
```
136136

137137
> [!NOTE]
138-
> In both Durable functions in-proc and in .NET-isolated, the orchestration input can be extracted via `context.GetInput<T>()`. However, .NET-isolated also supports the input being supplied as a parameter, as shown above. The input binding will bind to the first parameter which has no binding attribute on it and is not a well-known type already covered by other input bindings (ie: `FunctionContext`).
138+
> In both Durable functions in-proc and in .NET-isolated, the orchestration input can be extracted via `context.GetInput<T>()`. However, .NET-isolated also supports the input being supplied as a parameter, as shown above. The input binds to the first parameter, which has no binding attribute on it and isn't a well-known type already covered by other input bindings, such as `FunctionContext`.
139139
140140
---
141141

@@ -155,7 +155,7 @@ module.exports = df.orchestrator(function*(context) {
155155
> The `durable-functions` library takes care of calling the synchronous `context.done` method when the generator function exits.
156156
::: zone-end
157157
::: zone pivot="programming-language-python"
158-
# [v2](#tab/python-v2)
158+
### [v2](#tab/python-v2)
159159

160160
```python
161161
import azure.functions as func
@@ -169,7 +169,7 @@ def my_orchestrator(context):
169169
return result
170170
```
171171

172-
# [v1](#tab/python-v1)
172+
### [v1](#tab/python-v1)
173173
```python
174174
import azure.durable_functions as df
175175

@@ -204,7 +204,7 @@ public String helloWorldOrchestration(
204204
Most orchestrator functions call activity functions, so here is a "Hello World" example that demonstrates how to call an activity function:
205205
::: zone-end
206206
::: zone pivot="programming-language-csharp"
207-
# [In-process](#tab/in-process)
207+
### [In-process](#tab/in-process)
208208

209209
```csharp
210210
[FunctionName("HelloWorld")]
@@ -220,7 +220,7 @@ public static async Task<string> Run(
220220
> [!NOTE]
221221
> The previous code is for Durable Functions 2.x. For Durable Functions 1.x, you must use `DurableOrchestrationContext` instead of `IDurableOrchestrationContext`. For more information about the differences between versions, see the [Durable Functions versions](durable-functions-versions.md) article.
222222
223-
# [Isolated process](#tab/isolated-process)
223+
### [Isolated process](#tab/isolated-process)
224224

225225
```csharp
226226
[Function("HelloWorld")]
@@ -287,10 +287,10 @@ The activity trigger is defined by the following JSON object in the `bindings` a
287287
::: zone pivot="programming-language-python"
288288
The way that you define an activity trigger depends on your chosen programming model.
289289

290-
# [v2](#tab/python-v2)
290+
### [v2](#tab/python-v2)
291291
Using the `activity_trigger` decorator directly in your Python function code.
292292

293-
# [v1](#tab/python-v1)
293+
### [v1](#tab/python-v1)
294294
The activity trigger is defined by the following JSON object in the `bindings` array of *function.json*:
295295

296296
```json
@@ -323,15 +323,15 @@ Here are some notes about the activity trigger:
323323
The activity trigger binding supports both inputs and outputs, just like the orchestration trigger. Here are some things to know about input and output handling:
324324

325325
* **inputs** - Activity triggers can be invoked with inputs from an orchestrator function. All inputs must be JSON-serializable.
326-
* **outputs** - Activity functions support output values as well as inputs. The return value of the function is used to assign the output value and must be JSON-serializable.
326+
* **outputs** - Activity functions support both output and input values. The return value of the function is used to assign the output value and must be JSON-serializable.
327327
* **metadata** - .NET activity functions can bind to a `string instanceId` parameter to get the instance ID of the calling orchestration.
328328

329329
### Trigger sample
330330

331331
The following example code shows what a simple `SayHello` activity function might look like.
332332

333333
::: zone pivot="programming-language-csharp"
334-
# [In-process](#tab/in-process)
334+
### [In-process](#tab/in-process)
335335

336336
```csharp
337337
[FunctionName("SayHello")]
@@ -352,7 +352,7 @@ public static string SayHello([ActivityTrigger] string name)
352352
}
353353
```
354354

355-
# [Isolated process](#tab/isolated-process)
355+
### [Isolated process](#tab/isolated-process)
356356

357357
In the .NET-isolated worker, only serializable types representing your input are supported for the `[ActivityTrigger]`.
358358

@@ -374,7 +374,7 @@ module.exports = async function(context) {
374374
};
375375
```
376376

377-
JavaScript bindings can also be passed in as additional parameters, so the same function could be simplified as follows:
377+
JavaScript bindings can also be passed in as extra parameters, so the same function could be simplified as follows:
378378

379379
```javascript
380380
module.exports = async function(context, name) {
@@ -385,7 +385,7 @@ module.exports = async function(context, name) {
385385
::: zone-end
386386
::: zone pivot="programming-language-python"
387387

388-
# [v2](#tab/python-v2)
388+
### [v2](#tab/python-v2)
389389

390390
```python
391391
import azure.functions as func
@@ -398,7 +398,7 @@ def my_activity(myInput: str):
398398
return "Hello " + myInput
399399
```
400400

401-
# [v1](#tab/python-v1)
401+
### [v1](#tab/python-v1)
402402

403403
```python
404404
def main(name: str) -> str:
@@ -429,7 +429,7 @@ public String sayHello(@DurableActivityTrigger(name = "name") String name) {
429429
You can use regular input and output bindings in addition to the activity trigger binding.
430430

431431
::: zone pivot="programming-language-javascript"
432-
For example, you can take the input to your activity binding, and send a message to an Event Hub using the Event Hubs output binding:
432+
For example, you can take the input to your activity binding, and send a message to an event hub using the Event Hubs output binding:
433433

434434
```json
435435
{
@@ -495,10 +495,10 @@ The durable client trigger is defined by the following JSON object in the `bindi
495495
::: zone pivot="programming-language-python"
496496
The way that you define a durable client trigger depends on your chosen programming model.
497497

498-
# [v2](#tab/python-v2)
498+
### [v2](#tab/python-v2)
499499
Using the `durable_client_input` decorator directly in your Python function code.
500500

501-
# [v1](#tab/python-v1)
501+
### [v1](#tab/python-v1)
502502
The durable client trigger is defined by the following JSON object in the `bindings` array of *function.json*:
503503

504504
```json
@@ -536,7 +536,7 @@ Here's an example queue-triggered function that starts a "HelloWorld" orchestrat
536536

537537
::: zone pivot="programming-language-csharp"
538538

539-
# [In-process](#tab/in-process)
539+
#### [In-process](#tab/in-process)
540540

541541
```csharp
542542
[FunctionName("QueueStart")]
@@ -552,7 +552,7 @@ public static Task Run(
552552
> [!NOTE]
553553
> The previous C# code is for Durable Functions 2.x. For Durable Functions 1.x, you must use `OrchestrationClient` attribute instead of the `DurableClient` attribute, and you must use the `DurableOrchestrationClient` parameter type instead of `IDurableOrchestrationClient`. For more information about the differences between versions, see the [Durable Functions Versions](durable-functions-versions.md) article.
554554
555-
# [Isolated process](#tab/isolated-process)
555+
#### [Isolated process](#tab/isolated-process)
556556

557557
```csharp
558558
[Function("QueueStart")]
@@ -612,7 +612,7 @@ $InstanceId = Start-DurableOrchestration -FunctionName $FunctionName -Input $inp
612612
::: zone-end
613613
::: zone pivot="programming-language-python"
614614

615-
# [v2](#tab/python-v2)
615+
#### [v2](#tab/python-v2)
616616

617617
```python
618618
import azure.functions as func
@@ -629,7 +629,7 @@ async def durable_trigger(req: func.HttpRequest, client):
629629
return response
630630
```
631631

632-
# [v1](#tab/python-v1)
632+
#### [v1](#tab/python-v1)
633633

634634
**`function.json`**
635635
```json
@@ -739,12 +739,12 @@ By default, the name of an entity is the name of the function.
739739
> Entity triggers aren't yet supported for Java.
740740
::: zone-end
741741
::: zone pivot="programming-language-python"
742-
The way that you define a entity trigger depends on your chosen programming model.
742+
The way that you define an entity trigger depends on your chosen programming model.
743743

744-
# [v2](#tab/python-v2)
744+
#### [v2](#tab/python-v2)
745745
Using the `entity_trigger` decorator directly in your Python function code.
746746

747-
# [v1](#tab/python-v1)
747+
#### [v1](#tab/python-v1)
748748
The entity trigger is defined by the following JSON object in the `bindings` array of *function.json*:
749749

750750
```json
@@ -765,7 +765,7 @@ By default, the name of an entity is the name of the function.
765765

766766
Here are some notes about the entity trigger:
767767

768-
* **Single-threaded**: A single dispatcher thread is used to process operations for a particular entity. If multiple messages are sent to a single entity concurrently, the operations will be processed one-at-a-time.
768+
* **Single-threaded**: A single dispatcher thread is used to process operations for a particular entity. If multiple messages are sent to a single entity concurrently, the operations are processed one-at-a-time.
769769
* **Poison-message handling** - There's no poison message support in entity triggers.
770770
* **Message visibility** - Entity trigger messages are dequeued and kept invisible for a configurable duration. The visibility of these messages is renewed automatically as long as the function app is running and healthy.
771771
* **Return values** - Entity functions don't support return values. There are specific APIs that can be used to save state or pass values back to orchestrations.
@@ -805,12 +805,12 @@ The entity client is defined by the following JSON object in the `bindings` arra
805805
> In most cases, we recommend that you omit the optional properties and rely on the default behavior.
806806
::: zone-end
807807
::: zone pivot="programming-language-python"
808-
The way that you define a entity client depends on your chosen programming model.
808+
The way that you define an entity client depends on your chosen programming model.
809809

810-
# [v2](#tab/python-v2)
810+
#### [v2](#tab/python-v2)
811811
Using the `durable_client_input` decorator directly in your Python function code.
812812

813-
# [v1](#tab/python-v1)
813+
#### [v1](#tab/python-v1)
814814
The entity client is defined by the following JSON object in the `bindings` array of *function.json*:
815815

816816
```json

articles/azure-functions/durable/durable-functions-extension-upgrade.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ If you're using the Netherite or MSSQL [storage providers](durable-functions-sto
3333
* [MSSQL, isolated worker](https://www.nuget.org/packages/Microsoft.Azure.Functions.Worker.Extensions.DurableTask.SqlServer)
3434

3535
## Upgrade the extension bundle
36-
[Extension bundles](../functions-bindings-register.md#extension-bundles) provide an easy and convenient way for non-.NET function apps to reference and use various Azure Function triggers and bindings. For example, if you need to send a message to Event Hubs every time your function is triggered, you can use the Event Hubs extension to gain access to Event Hubs bindings. The Durable Functions extension is also included in each version of extension bundles. Extension bundles are automatically configured in host.json when creating a function app using any of the supported development tools.
36+
[Extension bundles](../extension-bundles.md) provide an easy and convenient way for non-.NET function apps to reference and use various Azure Function triggers and bindings. For example, if you need to send a message to Event Hubs every time your function is triggered, you can use the Event Hubs extension to gain access to Event Hubs bindings. The Durable Functions extension is also included in each version of extension bundles. Extension bundles are automatically configured in host.json when creating a function app using any of the supported development tools.
3737

3838
Most non-.NET applications rely on extension bundles to gain access to various triggers and bindings. The [latest bundle release](https://github.com/Azure/azure-functions-extension-bundles) often contains the latest version of the Durable Functions extension with critical bug fixes and performance improvements. Therefore, it's important that your app uses the latest version of extension bundles. You can check your host.json file to see whether the version range you're using includes the latest extension bundle version.
3939

0 commit comments

Comments
 (0)