Skip to content

Commit d7450f7

Browse files
committed
separate DF SDK classes from DF worker classes
fix typo DurableSDK now compiles by itself Allow ExternalSDK to handle orchestration document next steps allow external SDK to set the user-code's input. Still need to refactor this logic for the worker to continue working with old SDK add import module supress traces avoid nullptr pass tests fix E2E tests develop E2E tests Enabled external durable client (#765) Co-authored-by: Michael Peng <[email protected]> bindings work conditional binding intialization conditional import Added exception handling logic Revert durableController name to durableFunctionsUtils Ensure unit tests are functioning properly Corrected unit test names Turned repeated variables in unit tests into static members Fixed issue with building the worker Fix E2E test Fixed unit test setup Fixed another unit test setup Remove string representation of booleans patch e2e test remove typo in toString Update PowerShell language worker pipelines (#750) * Install .Net to a global location * Remove .Net installation tasks * Update install .Net 6 task * Update Windows image to use windows-latest Make throughput warning message visible for tooling diagnosis (#757) Update grpc.tools to version 2.43.0 Update Google.Protobuf.Tools to version 3.19.4 Revert "Update Google.Protobuf.Tools to version 3.19.4" This reverts commit bcbd022. Revert "Update grpc.tools to version 2.43.0" This reverts commit ccb323a. Update Google.Protobuf to 3.19.4 and grpc.tools to 2.43.0 (#762) * Update grpc.tools to version 2.43.0 * Update Google.Protobuf.Tools to version 3.19.4 Switch from Grpc.Core to Grpc.Net.Client (#758) * Upgraded protobuf versions and removed Grpc.Core dependency * Updated channel and option types used * Change channel credentials * Added http prefix to url * Add valid URL check and explicitly include credentials Update pipeline logic to generate the SBOM for release builds (#767) Return results from Start-DurableExternalEventListener (#685) (#753) Co-authored-by: Greg Roll <[email protected]> add e2e test for GetTaskResult parametrize test patch new e2e test patch external contrib fix typo in test comment changes Adds IExternalInvoker (#776) * Define a contract for the external invoker * Remove extraneous comments and variables rename hasOrchestrationContext to hasInitializedDurableFunction remove outdated TODO comment remove now unused function - CreateOrchestrationBindingInfo Allow worker to read results directly from the external SDK (#777) comment out external SDK path
1 parent 3642ec0 commit d7450f7

22 files changed

+315
-142
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
#pragma warning disable 1591 // Missing XML comment for publicly visible type or member 'member'
7+
8+
namespace Microsoft.Azure.Functions.PowerShellWorker.Durable.Commands
9+
{
10+
using System.Collections;
11+
using System.Management.Automation;
12+
using Microsoft.Azure.Functions.PowerShellWorker.Durable.Tasks;
13+
14+
[Cmdlet("Get", "DurableTaskResult")]
15+
public class GetDurableTaskResultCommand : PSCmdlet
16+
{
17+
[Parameter(Mandatory = true)]
18+
[ValidateNotNull]
19+
public DurableTask[] Task { get; set; }
20+
21+
private readonly DurableTaskHandler _durableTaskHandler = new DurableTaskHandler();
22+
23+
protected override void EndProcessing()
24+
{
25+
var privateData = (Hashtable)MyInvocation.MyCommand.Module.PrivateData;
26+
var context = (OrchestrationContext)privateData[SetFunctionInvocationContextCommand.ContextKey];
27+
28+
_durableTaskHandler.GetTaskResult(Task, context, WriteObject);
29+
}
30+
31+
protected override void StopProcessing()
32+
{
33+
_durableTaskHandler.Stop();
34+
}
35+
}
36+
}

src/DurableSDK/DurableTaskHandler.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ public void WaitAny(
175175
if (scheduledHistoryEvent != null)
176176
{
177177
scheduledHistoryEvent.IsProcessed = true;
178+
scheduledHistoryEvent.IsPlayed = true;
178179
}
179180

180181
if (completedHistoryEvent != null)
@@ -190,6 +191,7 @@ public void WaitAny(
190191
}
191192

192193
completedHistoryEvent.IsProcessed = true;
194+
completedHistoryEvent.IsPlayed = true;
193195
}
194196
}
195197

@@ -207,6 +209,21 @@ public void WaitAny(
207209
}
208210
}
209211

212+
public void GetTaskResult(
213+
IReadOnlyCollection<DurableTask> tasksToQueryResultFor,
214+
OrchestrationContext context,
215+
Action<object> output)
216+
{
217+
foreach (var task in tasksToQueryResultFor) {
218+
var scheduledHistoryEvent = task.GetScheduledHistoryEvent(context, true);
219+
var processedHistoryEvent = task.GetCompletedHistoryEvent(context, scheduledHistoryEvent, true);
220+
if (processedHistoryEvent != null)
221+
{
222+
output(GetEventResult(processedHistoryEvent));
223+
}
224+
}
225+
}
226+
210227
public void Stop()
211228
{
212229
_waitForStop.Set();

src/DurableSDK/ExternalInvoker.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
namespace Microsoft.Azure.Functions.PowerShellWorker.Durable
7+
{
8+
using System;
9+
using System.Collections;
10+
using System.Management.Automation;
11+
12+
internal class ExternalInvoker : IExternalInvoker
13+
{
14+
private readonly Func<PowerShell, object> _externalSDKInvokerFunction;
15+
16+
public ExternalInvoker(Func<PowerShell, object> invokerFunction)
17+
{
18+
_externalSDKInvokerFunction = invokerFunction;
19+
}
20+
21+
public Hashtable Invoke(IPowerShellServices powerShellServices)
22+
{
23+
return (Hashtable)_externalSDKInvokerFunction.Invoke(powerShellServices.GetPowerShell());
24+
}
25+
}
26+
}

src/DurableSDK/IExternalInvoker.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
namespace Microsoft.Azure.Functions.PowerShellWorker.Durable
7+
{
8+
using System.Collections;
9+
10+
// Represents a contract for the
11+
internal interface IExternalInvoker
12+
{
13+
// Method to invoke an orchestration using the external Durable SDK
14+
Hashtable Invoke(IPowerShellServices powerShellServices);
15+
}
16+
}

src/DurableSDK/IOrchestrationInvoker.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55

66
namespace Microsoft.Azure.Functions.PowerShellWorker.Durable
77
{
8-
using System;
98
using System.Collections;
10-
using System.Management.Automation;
119

1210
internal interface IOrchestrationInvoker
1311
{
1412
Hashtable Invoke(OrchestrationBindingInfo orchestrationBindingInfo, IPowerShellServices pwsh);
15-
void SetExternalInvoker(Action<PowerShell> externalInvoker);
13+
void SetExternalInvoker(IExternalInvoker externalInvoker);
1614
}
1715
}

src/DurableSDK/IPowerShellServices.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ internal interface IPowerShellServices
1717

1818
void SetDurableClient(object durableClient);
1919

20-
OrchestrationBindingInfo SetOrchestrationContext(ParameterBinding orchestrationContext, out Action<object> externalInvoker);
20+
OrchestrationBindingInfo SetOrchestrationContext(ParameterBinding context, out IExternalInvoker externalInvoker);
2121

2222
void ClearOrchestrationContext();
2323

24-
public void TracePipelineObject();
25-
public void AddParameter(string name, object value);
24+
void TracePipelineObject();
2625

26+
void AddParameter(string name, object value);
2727

2828
IAsyncResult BeginInvoke(PSDataCollection<object> output);
2929

src/DurableSDK/OrchestrationContext.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,6 @@ public class OrchestrationContext
3535

3636
internal OrchestrationActionCollector OrchestrationActionCollector { get; } = new OrchestrationActionCollector();
3737

38-
internal object ExternalResult;
39-
internal bool ExternalIsError;
40-
41-
internal void SetExternalResult(object result, bool isError)
42-
{
43-
this.ExternalResult = result;
44-
this.ExternalIsError = isError;
45-
}
46-
4738
internal object CustomStatus { get; set; }
4839
}
4940
}

src/DurableSDK/OrchestrationInvoker.cs

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,81 +11,88 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.Durable
1111
using System.Linq;
1212
using System.Management.Automation;
1313

14-
// using PowerShellWorker.Utility;
1514
using Microsoft.Azure.Functions.PowerShellWorker.Durable.Actions;
1615

1716
internal class OrchestrationInvoker : IOrchestrationInvoker
1817
{
19-
private Action<PowerShell> externalInvoker = null;
18+
private IExternalInvoker _externalInvoker;
19+
internal static string isOrchestrationFailureKey = "IsOrchestrationFailure";
2020

21-
public Hashtable Invoke(OrchestrationBindingInfo orchestrationBindingInfo, IPowerShellServices pwsh)
21+
public Hashtable Invoke(
22+
OrchestrationBindingInfo orchestrationBindingInfo,
23+
IPowerShellServices powerShellServices)
2224
{
23-
2425
try
2526
{
26-
if (pwsh.UseExternalDurableSDK())
27+
if (powerShellServices.UseExternalDurableSDK())
2728
{
28-
externalInvoker.Invoke(pwsh.GetPowerShell());
29-
var result = orchestrationBindingInfo.Context.ExternalResult;
30-
var isError = orchestrationBindingInfo.Context.ExternalIsError;
31-
if (isError)
32-
{
33-
throw (Exception)result;
34-
}
35-
else
36-
{
37-
return (Hashtable)result;
38-
}
29+
return InvokeExternalDurableSDK(powerShellServices);
3930
}
31+
return InvokeInternalDurableSDK(orchestrationBindingInfo, powerShellServices);
32+
}
33+
catch (Exception ex)
34+
{
35+
ex.Data.Add(isOrchestrationFailureKey, true);
36+
throw;
37+
}
38+
finally
39+
{
40+
powerShellServices.ClearStreamsAndCommands();
41+
}
42+
}
4043

41-
var outputBuffer = new PSDataCollection<object>();
42-
var context = orchestrationBindingInfo.Context;
44+
public Hashtable InvokeExternalDurableSDK(IPowerShellServices powerShellServices)
45+
{
46+
return _externalInvoker.Invoke(powerShellServices);
47+
}
4348

44-
// context.History should never be null when initializing CurrentUtcDateTime
45-
var orchestrationStart = context.History.First(
46-
e => e.EventType == HistoryEventType.OrchestratorStarted);
47-
context.CurrentUtcDateTime = orchestrationStart.Timestamp.ToUniversalTime();
49+
public Hashtable InvokeInternalDurableSDK(
50+
OrchestrationBindingInfo orchestrationBindingInfo,
51+
IPowerShellServices powerShellServices)
52+
{
53+
var outputBuffer = new PSDataCollection<object>();
54+
var context = orchestrationBindingInfo.Context;
4855

49-
// Marks the first OrchestratorStarted event as processed
50-
orchestrationStart.IsProcessed = true;
56+
// context.History should never be null when initializing CurrentUtcDateTime
57+
var orchestrationStart = context.History.First(
58+
e => e.EventType == HistoryEventType.OrchestratorStarted);
59+
context.CurrentUtcDateTime = orchestrationStart.Timestamp.ToUniversalTime();
5160

61+
// Marks the first OrchestratorStarted event as processed
62+
orchestrationStart.IsProcessed = true;
5263

53-
pwsh.AddParameter(orchestrationBindingInfo.ParameterName, context);
54-
pwsh.TracePipelineObject();
64+
// Finish initializing the Function invocation
65+
powerShellServices.AddParameter(orchestrationBindingInfo.ParameterName, context);
66+
powerShellServices.TracePipelineObject();
5567

56-
var asyncResult = pwsh.BeginInvoke(outputBuffer);
68+
var asyncResult = powerShellServices.BeginInvoke(outputBuffer);
5769

58-
var (shouldStop, actions) =
59-
orchestrationBindingInfo.Context.OrchestrationActionCollector.WaitForActions(asyncResult.AsyncWaitHandle);
70+
var (shouldStop, actions) =
71+
orchestrationBindingInfo.Context.OrchestrationActionCollector.WaitForActions(asyncResult.AsyncWaitHandle);
6072

61-
if (shouldStop)
73+
if (shouldStop)
74+
{
75+
// The orchestration function should be stopped and restarted
76+
powerShellServices.StopInvoke();
77+
// return (Hashtable)orchestrationBindingInfo.Context.OrchestrationActionCollector.output;
78+
return CreateOrchestrationResult(isDone: false, actions, output: null, context.CustomStatus);
79+
}
80+
else
81+
{
82+
try
6283
{
63-
// The orchestration function should be stopped and restarted
64-
pwsh.StopInvoke();
65-
// return (Hashtable)orchestrationBindingInfo.Context.OrchestrationActionCollector.output;
66-
return CreateOrchestrationResult(isDone: false, actions, output: null, context.CustomStatus);
84+
// The orchestration function completed
85+
powerShellServices.EndInvoke(asyncResult);
86+
var result = CreateReturnValueFromFunctionOutput(outputBuffer);
87+
return CreateOrchestrationResult(isDone: true, actions, output: result, context.CustomStatus);
6788
}
68-
else
89+
catch (Exception e)
6990
{
70-
try
71-
{
72-
// The orchestration function completed
73-
pwsh.EndInvoke(asyncResult);
74-
var result = CreateReturnValueFromFunctionOutput(outputBuffer);
75-
return CreateOrchestrationResult(isDone: true, actions, output: result, context.CustomStatus);
76-
}
77-
catch (Exception e)
78-
{
79-
// The orchestrator code has thrown an unhandled exception:
80-
// this should be treated as an entire orchestration failure
81-
throw new OrchestrationFailureException(actions, context.CustomStatus, e);
82-
}
91+
// The orchestrator code has thrown an unhandled exception:
92+
// this should be treated as an entire orchestration failure
93+
throw new OrchestrationFailureException(actions, context.CustomStatus, e);
8394
}
8495
}
85-
finally
86-
{
87-
pwsh.ClearStreamsAndCommands();
88-
}
8996
}
9097

9198
public static object CreateReturnValueFromFunctionOutput(IList<object> pipelineItems)
@@ -108,9 +115,9 @@ private static Hashtable CreateOrchestrationResult(
108115
return new Hashtable { { "$return", orchestrationMessage } };
109116
}
110117

111-
public void SetExternalInvoker(Action<PowerShell> externalInvoker)
118+
public void SetExternalInvoker(IExternalInvoker externalInvoker)
112119
{
113-
this.externalInvoker = externalInvoker;
120+
_externalInvoker = externalInvoker;
114121
}
115122
}
116123
}

0 commit comments

Comments
 (0)