Skip to content

Commit 97605f3

Browse files
authored
Merge pull request #87635 from MicrosoftDocs/master
Merge Master to Live, 3 AM
2 parents 88ae439 + ad9ce60 commit 97605f3

File tree

110 files changed

+1290
-1401
lines changed

Some content is hidden

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

110 files changed

+1290
-1401
lines changed

.openpublishing.redirection.json

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36525,19 +36525,29 @@
3652536525
},
3652636526
{
3652736527
"source_path": "articles/monitoring-and-diagnostics/azure-diagnostics-schema-1dot0.md",
36528-
"redirect_url": "/azure/azure-monitor/platform/diagnostics-extension-schema-1dot0",
36529-
"redirect_document_id": true
36528+
"redirect_url": "/azure/azure-monitor/platform/diagnostics-extension-schema-1dot3",
36529+
"redirect_document_id": false
3653036530
},
3653136531
{
3653236532
"source_path": "articles/monitoring-and-diagnostics/azure-diagnostics-schema-1dot2.md",
36533-
"redirect_url": "/azure/azure-monitor/platform/diagnostics-extension-schema-1dot2",
36534-
"redirect_document_id": true
36533+
"redirect_url": "/azure/azure-monitor/platform/diagnostics-extension-schema-1dot3",
36534+
"redirect_document_id": false
3653536535
},
3653636536
{
3653736537
"source_path": "articles/monitoring-and-diagnostics/azure-diagnostics-schema-1dot3-and-later.md",
3653836538
"redirect_url": "/azure/azure-monitor/platform/diagnostics-extension-schema-1dot3",
3653936539
"redirect_document_id": true
36540-
},
36540+
},
36541+
{
36542+
"source_path": "articles/azure-monitor/platform/azure-diagnostics-schema-1dot0.md",
36543+
"redirect_url": "/azure/azure-monitor/platform/diagnostics-extension-schema-1dot3",
36544+
"redirect_document_id": false
36545+
},
36546+
{
36547+
"source_path": "articles/azure-monitor/platform/azure-diagnostics-schema-1dot2.md",
36548+
"redirect_url": "/azure/azure-monitor/platform/diagnostics-extension-schema-1dot3",
36549+
"redirect_document_id": false
36550+
},
3654136551
{
3654236552
"source_path": "articles/monitoring-and-diagnostics/azure-diagnostics-storage.md",
3654336553
"redirect_url": "/azure/azure-monitor/platform/diagnostics-extension-to-storage",

articles/active-directory/users-groups-roles/directory-assign-admin-roles.md

Lines changed: 366 additions & 356 deletions
Large diffs are not rendered by default.

articles/azure-functions/durable/durable-functions-checkpointing-and-replay.md

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ title: Checkpoints and replay in Durable Functions - Azure
33
description: Learn how checkpointing and reply works in the Durable Functions extension for Azure Functions.
44
services: functions
55
author: ggailey777
6-
manager: jeconnoc
7-
keywords:
6+
manager: gwallace
87
ms.service: azure-functions
98
ms.topic: conceptual
109
ms.date: 12/07/2018
@@ -123,17 +122,9 @@ The replay behavior creates constraints on the type of code that can be written
123122

124123
If orchestrator code needs to get the current date/time, it should use the [CurrentUtcDateTime](https://azure.github.io/azure-functions-durable-extension/api/Microsoft.Azure.WebJobs.DurableOrchestrationContext.html#Microsoft_Azure_WebJobs_DurableOrchestrationContext_CurrentUtcDateTime) (.NET) or `currentUtcDateTime` (JavaScript) API, which is safe for replay.
125124

126-
If orchestrator code needs to generate a random GUID, it should use the [NewGuid](https://azure.github.io/azure-functions-durable-extension/api/Microsoft.Azure.WebJobs.DurableOrchestrationContext.html#Microsoft_Azure_WebJobs_DurableOrchestrationContext_NewGuid) (.NET) API, which is safe for replay, or delegate GUID generation to an activity function (JavaScript), as in this example:
125+
If orchestrator code needs to generate a random GUID, it should use either the [NewGuid](https://azure.github.io/azure-functions-durable-extension/api/Microsoft.Azure.WebJobs.DurableOrchestrationContext.html#Microsoft_Azure_WebJobs_DurableOrchestrationContext_NewGuid) (.NET) or the `newGuid` (JavaScript) API, which is safe for replay.
127126

128-
```javascript
129-
const uuid = require("uuid/v1");
130-
131-
module.exports = async function(context) {
132-
return uuid();
133-
}
134-
```
135-
136-
Non-deterministic operations must be done in activity functions. This includes any interaction with other input or output bindings. This ensures that any non-deterministic values will be generated once on the first execution and saved into the execution history. Subsequent executions will then use the saved value automatically.
127+
Other than these special cases, non-deterministic operations must be done in activity functions. This includes any interaction with other input or output bindings. This ensures that any non-deterministic values will be generated once on the first execution and saved into the execution history. Subsequent executions will then use the saved value automatically.
137128

138129
* Orchestrator code should be **non-blocking**. For example, that means no I/O and no calls to `Thread.Sleep` (.NET) or equivalent APIs.
139130

@@ -160,7 +151,7 @@ While these constraints may seem daunting at first, in practice they aren't hard
160151
161152
Tasks that can be safely awaited in orchestrator functions are occasionally referred to as *durable tasks*. These are tasks that are created and managed by the Durable Task Framework. Examples are the tasks returned by `CallActivityAsync`, `WaitForExternalEvent`, and `CreateTimer`.
162153

163-
These *durable tasks* are internally managed by using a list of `TaskCompletionSource` objects. During replay, these tasks get created as part of orchestrator code execution and are completed as the dispatcher enumerates the corresponding history events. This is all done synchronously using a single thread until all the history has been replayed. Any durable tasks, which are not completed by the end of history replay has appropriate actions carried out. For example, a message may be enqueued to call an activity function.
154+
These *durable tasks* are internally managed by using a list of `TaskCompletionSource` objects. During replay, these tasks get created as part of orchestrator code execution and are completed as the dispatcher enumerates the corresponding history events. This is all done synchronously using a single thread until all the history has been replayed. Any durable tasks that are not completed by the end of history replay have appropriate actions carried out. For example, a message may be enqueued to call an activity function.
164155

165156
The execution behavior described here should help you understand why orchestrator function code must never `await` a non-durable task: the dispatcher thread cannot wait for it to complete and any callback by that task could potentially corrupt the tracking state of the orchestrator function. Some runtime checks are in place to try to prevent this.
166157

@@ -169,4 +160,4 @@ If you'd like more information about how the Durable Task Framework executes orc
169160
## Next steps
170161

171162
> [!div class="nextstepaction"]
172-
> [Learn about instance management](durable-functions-instance-management.md)
163+
> [Learn about instance management](durable-functions-instance-management.md)

articles/azure-functions/durable/durable-functions-cloud-backup.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,4 @@ Here is the orchestration as a single C# file in a Visual Studio project:
177177
This sample has shown how to implement the fan-out/fan-in pattern. The next sample shows how to implement the monitor pattern using [durable timers](durable-functions-timers.md).
178178

179179
> [!div class="nextstepaction"]
180-
> [Run the monitor sample](durable-functions-monitor.md)
180+
> [Run the monitor sample](durable-functions-monitor.md)

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

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,25 @@ In the function chaining pattern, a sequence of functions executes in a specific
3333

3434
You can use Durable Functions to implement the function chaining pattern concisely as shown in the following example:
3535

36+
#### Precompiled C#
37+
38+
```csharp
39+
public static async Task<object> Run([OrchestrationTrigger] DurableOrchestrationContext context)
40+
{
41+
try
42+
{
43+
var x = await context.CallActivityAsync<object>("F1");
44+
var y = await context.CallActivityAsync<object>("F2", x);
45+
var z = await context.CallActivityAsync<object>("F3", y);
46+
return await context.CallActivityAsync<object>("F4", z);
47+
}
48+
catch (Exception)
49+
{
50+
// Error handling or compensation goes here.
51+
}
52+
}
53+
```
54+
3655
#### C# script
3756

3857
```csharp
@@ -53,7 +72,7 @@ public static async Task<object> Run(DurableOrchestrationContext context)
5372
```
5473

5574
> [!NOTE]
56-
> There are subtle differences between writing a precompiled durable function in C# and writing a precompiled durable function in the C# script that's shown in the example. In a C# precompiled function, durable parameters must be decorated with respective attributes. An example is the `[OrchestrationTrigger]` attribute for the `DurableOrchestrationContext` parameter. In a C# precompiled durable function, if the parameters aren't properly decorated, the runtime can't inject the variables into the function, and an error occurs. For more examples, see the [azure-functions-durable-extension samples on GitHub](https://github.com/Azure/azure-functions-durable-extension/blob/master/samples).
75+
> There are subtle differences between writing a precompiled durable function in C# and writing a precompiled durable function in C# script. In a C# precompiled function, durable parameters must be decorated with respective attributes. An example is the `[OrchestrationTrigger]` attribute for the `DurableOrchestrationContext` parameter. In a C# precompiled durable function, if the parameters aren't properly decorated, the runtime can't inject the variables into the function, and an error occurs. For more examples, see the [azure-functions-durable-extension samples on GitHub](https://github.com/Azure/azure-functions-durable-extension/blob/master/samples).
5776
5877
#### JavaScript (Functions 2.x only)
5978

@@ -85,6 +104,29 @@ With normal functions, you can fan out by having the function send multiple mess
85104

86105
The Durable Functions extension handles this pattern with relatively simple code:
87106

107+
#### Precompiled C#
108+
109+
```csharp
110+
public static async Task Run([OrchestrationTrigger] DurableOrchestrationContext context)
111+
{
112+
var parallelTasks = new List<Task<int>>();
113+
114+
// Get a list of N work items to process in parallel.
115+
object[] workBatch = await context.CallActivityAsync<object[]>("F1");
116+
for (int i = 0; i < workBatch.Length; i++)
117+
{
118+
Task<int> task = context.CallActivityAsync<int>("F2", workBatch[i]);
119+
parallelTasks.Add(task);
120+
}
121+
122+
await Task.WhenAll(parallelTasks);
123+
124+
// Aggregate all N outputs and send the result to F3.
125+
int sum = parallelTasks.Sum(t => t.Result);
126+
await context.CallActivityAsync("F3", sum);
127+
}
128+
```
129+
88130
#### C# script
89131

90132
```csharp
@@ -173,7 +215,29 @@ The Durable Functions extension has built-in webhooks that manage long-running o
173215

174216
Here are some examples of how to use the HTTP API pattern:
175217

176-
#### C#
218+
#### Precompiled C#
219+
220+
```csharp
221+
// An HTTP-triggered function starts a new orchestrator function instance.
222+
[FunctionName("StartNewOrchestration")]
223+
public static async Task<HttpResponseMessage> Run(
224+
[HttpTrigger] HttpRequestMessage req,
225+
[OrchestrationClient] DurableOrchestrationClient starter,
226+
string functionName,
227+
ILogger log)
228+
{
229+
// The function name comes from the request URL.
230+
// The function input comes from the request content.
231+
dynamic eventData = await req.Content.ReadAsAsync<object>();
232+
string instanceId = await starter.StartNewAsync(functionName, eventData);
233+
234+
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
235+
236+
return starter.CreateCheckStatusResponse(req, instanceId);
237+
}
238+
```
239+
240+
#### C# script
177241

178242
```csharp
179243
// An HTTP-triggered function starts a new orchestrator function instance.
@@ -230,6 +294,35 @@ In a few lines of code, you can use Durable Functions to create multiple monitor
230294

231295
The following code implements a basic monitor:
232296

297+
#### Precompiled C#
298+
299+
```csharp
300+
[FunctionName("Orchestrator")]
301+
public static async Task Run([OrchestrationTrigger] DurableOrchestrationContext context)
302+
{
303+
int jobId = context.GetInput<int>();
304+
int pollingInterval = GetPollingInterval();
305+
DateTime expiryTime = GetExpiryTime();
306+
307+
while (context.CurrentUtcDateTime < expiryTime)
308+
{
309+
var jobStatus = await context.CallActivityAsync<string>("GetJobStatus", jobId);
310+
if (jobStatus == "Completed")
311+
{
312+
// Perform an action when a condition is met.
313+
await context.CallActivityAsync("SendAlert", machineId);
314+
break;
315+
}
316+
317+
// Orchestration sleeps until this time.
318+
var nextCheck = context.CurrentUtcDateTime.AddSeconds(pollingInterval);
319+
await context.CreateTimer(nextCheck, CancellationToken.None);
320+
}
321+
322+
// Perform more work here, or let the orchestration end.
323+
}
324+
```
325+
233326
#### C# script
234327

235328
```csharp
@@ -300,6 +393,32 @@ You can implement the pattern in this example by using an orchestrator function.
300393

301394
These examples create an approval process to demonstrate the human interaction pattern:
302395

396+
#### Precompiled C#
397+
398+
```csharp
399+
[FunctionName("Orchestrator")]
400+
public static async Task Run([OrchestrationTrigger] DurableOrchestrationContext context)
401+
{
402+
await context.CallActivityAsync("RequestApproval");
403+
using (var timeoutCts = new CancellationTokenSource())
404+
{
405+
DateTime dueTime = context.CurrentUtcDateTime.AddHours(72);
406+
Task durableTimeout = context.CreateTimer(dueTime, timeoutCts.Token);
407+
408+
Task<bool> approvalEvent = context.WaitForExternalEvent<bool>("ApprovalEvent");
409+
if (approvalEvent == await Task.WhenAny(approvalEvent, durableTimeout))
410+
{
411+
timeoutCts.Cancel();
412+
await context.CallActivityAsync("ProcessApproval", approvalEvent.Result);
413+
}
414+
else
415+
{
416+
await context.CallActivityAsync("Escalate");
417+
}
418+
}
419+
}
420+
```
421+
303422
#### C# script
304423

305424
```csharp
@@ -351,6 +470,20 @@ To create the durable timer, call `context.CreateTimer` (.NET) or `context.df.cr
351470

352471
An external client can deliver the event notification to a waiting orchestrator function by using either the [built-in HTTP APIs](durable-functions-http-api.md#raise-event) or by using the [DurableOrchestrationClient.RaiseEventAsync](https://azure.github.io/azure-functions-durable-extension/api/Microsoft.Azure.WebJobs.DurableOrchestrationClient.html#Microsoft_Azure_WebJobs_DurableOrchestrationClient_RaiseEventAsync_System_String_System_String_System_Object_) API from another function:
353472

473+
#### Precompiled C#
474+
475+
```csharp
476+
public static async Task Run(
477+
[HttpTrigger] string instanceId,
478+
[OrchestrationClient] DurableOrchestrationClient client)
479+
{
480+
bool isApproved = true;
481+
await client.RaiseEventAsync(instanceId, "ApprovalEvent", isApproved);
482+
}
483+
```
484+
485+
#### C# Script
486+
354487
```csharp
355488
public static async Task Run(string instanceId, DurableOrchestrationClient client)
356489
{
@@ -359,6 +492,8 @@ public static async Task Run(string instanceId, DurableOrchestrationClient clien
359492
}
360493
```
361494

495+
#### Javascript
496+
362497
```javascript
363498
const df = require("durable-functions");
364499

@@ -507,4 +642,4 @@ To get started:
507642
> [!div class="nextstepaction"]
508643
> [Create your first durable function](durable-functions-create-first-csharp.md)
509644
510-
[DurableOrchestrationContext]: https://azure.github.io/azure-functions-durable-extension/api/Microsoft.Azure.WebJobs.DurableOrchestrationContext.html
645+
[DurableOrchestrationContext]: https://azure.github.io/azure-functions-durable-extension/api/Microsoft.Azure.WebJobs.DurableOrchestrationContext.html

articles/azure-functions/durable/durable-functions-create-first-csharp.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,4 @@ You must have a function app in your Azure subscription before you can publish y
140140
You have used Visual Studio to create and publish a C# durable function app.
141141

142142
> [!div class="nextstepaction"]
143-
> [Learn about common durable function patterns.](durable-functions-concepts.md)
143+
> [Learn about common durable function patterns.](durable-functions-concepts.md)

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

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,26 @@ The result is a list of instance IDs and their current runtime status.
153153

154154
It's important to keep the orchestrator replay behavior in mind when writing logs directly from an orchestrator function. For example, consider the following orchestrator function:
155155

156-
### C#
156+
### Precompiled C#
157157

158-
```cs
158+
```csharp
159+
public static async Task Run(
160+
[OrchestrationTrigger] DurableOrchestrationContext context,
161+
ILogger log)
162+
{
163+
log.LogInformation("Calling F1.");
164+
await context.CallActivityAsync("F1");
165+
log.LogInformation("Calling F2.");
166+
await context.CallActivityAsync("F2");
167+
log.LogInformation("Calling F3");
168+
await context.CallActivityAsync("F3");
169+
log.LogInformation("Done!");
170+
}
171+
```
172+
173+
### C# Script
174+
175+
```csharp
159176
public static async Task Run(
160177
DurableOrchestrationContext context,
161178
ILogger log)
@@ -206,6 +223,23 @@ Done!
206223
207224
If you want to only log on non-replay execution, you can write a conditional expression to log only if `IsReplaying` is `false`. Consider the example above, but this time with replay checks.
208225

226+
#### Precompiled C#
227+
228+
```csharp
229+
public static async Task Run(
230+
[OrchestrationTrigger] DurableOrchestrationContext context,
231+
ILogger log)
232+
{
233+
if (!context.IsReplaying) log.LogInformation("Calling F1.");
234+
await context.CallActivityAsync("F1");
235+
if (!context.IsReplaying) log.LogInformation("Calling F2.");
236+
await context.CallActivityAsync("F2");
237+
if (!context.IsReplaying) log.LogInformation("Calling F3");
238+
await context.CallActivityAsync("F3");
239+
log.LogInformation("Done!");
240+
}
241+
```
242+
209243
#### C#
210244

211245
```cs
@@ -252,7 +286,7 @@ Done!
252286

253287
Custom orchestration status lets you set a custom status value for your orchestrator function. This status is provided via the HTTP status query API or the `DurableOrchestrationClient.GetStatusAsync` API. The custom orchestration status enables richer monitoring for orchestrator functions. For example, the orchestrator function code can include `DurableOrchestrationContext.SetCustomStatus` calls to update the progress for a long-running operation. A client, such as a web page or other external system, could then periodically query the HTTP status query APIs for richer progress information. A sample using `DurableOrchestrationContext.SetCustomStatus` is provided below:
254288

255-
### C#
289+
### Precompiled C#
256290

257291
```csharp
258292
public static async Task SetStatusTest([OrchestrationTrigger] DurableOrchestrationContext context)
@@ -331,4 +365,4 @@ This is useful for debugging because you see exactly what state an orchestration
331365
## Next steps
332366

333367
> [!div class="nextstepaction"]
334-
> [Learn how to use durable timers](durable-functions-timers.md)
368+
> [Learn how to use durable timers](durable-functions-timers.md)

0 commit comments

Comments
 (0)