Skip to content

Commit 1010f97

Browse files
committed
pass tests
1 parent 47caee9 commit 1010f97

File tree

8 files changed

+80
-72
lines changed

8 files changed

+80
-72
lines changed

src/DurableSDK/DurableTaskHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public void WaitAll(
136136
var allTasksCompleted = completedEvents.Count == tasksToWaitFor.Count;
137137
if (allTasksCompleted)
138138
{
139-
context.IsReplaying = completedEvents[0].IsPlayed;
139+
context.IsReplaying = completedEvents.Count == 0 ? false : completedEvents[0].IsPlayed;
140140
CurrentUtcDateTimeUpdater.UpdateCurrentUtcDateTime(context);
141141

142142
foreach (var completedHistoryEvent in completedEvents)

src/DurableSDK/IPowerShellServices.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,18 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.Durable
1111
internal interface IPowerShellServices
1212
{
1313
PowerShell GetPowerShell();
14+
15+
bool UsesExternalDurableSDK();
1416
void SetDurableClient(object durableClient);
1517

1618
void SetOrchestrationContext(OrchestrationContext orchestrationContext);
1719

1820
void ClearOrchestrationContext();
1921

22+
public void TracePipelineObject();
23+
public void AddParameter(string name, object value);
24+
25+
2026
IAsyncResult BeginInvoke(PSDataCollection<object> output);
2127

2228
void EndInvoke(IAsyncResult asyncResult);

src/DurableSDK/OrchestrationInvoker.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ internal class OrchestrationInvoker : IOrchestrationInvoker
2121
public Hashtable Invoke(OrchestrationBindingInfo orchestrationBindingInfo, IPowerShellServices pwsh)
2222
{
2323

24-
25-
pwsh.GetPowerShell()?.AddCommand("Microsoft.Azure.Functions.PowerShellWorker\\Trace-PipelineObject");
26-
2724
try
2825
{
2926
var outputBuffer = new PSDataCollection<object>();
@@ -52,7 +49,9 @@ public Hashtable Invoke(OrchestrationBindingInfo orchestrationBindingInfo, IPowe
5249
return (Hashtable)result;
5350
}
5451
}
55-
52+
pwsh.AddParameter(orchestrationBindingInfo.ParameterName, context);
53+
pwsh.TracePipelineObject();
54+
5655
var asyncResult = pwsh.BeginInvoke(outputBuffer);
5756

5857
var (shouldStop, actions) =

src/DurableSDK/PowerShellServices.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ public PowerShell GetPowerShell()
2626
return this._pwsh;
2727
}
2828

29+
public bool UsesExternalDurableSDK()
30+
{
31+
this._pwsh.AddCommand("Import-Module")
32+
.AddParameter("Name", "DurableSDK")
33+
.InvokeAndClearCommands<Action<object>>();
34+
return false;
35+
}
36+
2937
public void SetDurableClient(object durableClient)
3038
{
3139
_pwsh.AddCommand(SetFunctionInvocationContextCommand)
@@ -45,6 +53,11 @@ public void SetOrchestrationContext(OrchestrationContext orchestrationContext)
4553
_hasSetOrchestrationContext = true;
4654
}
4755

56+
public void AddParameter(string name, object value)
57+
{
58+
_pwsh.AddParameter(name, value);
59+
}
60+
4861
public void ClearOrchestrationContext()
4962
{
5063
if (_hasSetOrchestrationContext)
@@ -55,6 +68,11 @@ public void ClearOrchestrationContext()
5568
}
5669
}
5770

71+
public void TracePipelineObject()
72+
{
73+
_pwsh.AddCommand("Microsoft.Azure.Functions.PowerShellWorker\\Trace-PipelineObject");
74+
}
75+
5876
public IAsyncResult BeginInvoke(PSDataCollection<object> output)
5977
{
6078
return _pwsh.BeginInvoke<object, object>(input: null, output);

src/DurableWorker/DurableController.cs

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ internal DurableController(
5050
_orchestrationInvoker = orchestrationInvoker;
5151
}
5252

53-
public void BeforeFunctionInvocation(IList<ParameterBinding> inputData)
53+
public string GetOrchestrationParameterName()
54+
{
55+
return _orchestrationBindingInfo?.ParameterName;
56+
}
57+
58+
public void InitializeBindings(IList<ParameterBinding> inputData)
5459
{
5560
// If the function is an orchestration client, then we set the DurableClient
5661
// in the module context for the 'Start-DurableOrchestration' function to use.
@@ -60,18 +65,6 @@ public void BeforeFunctionInvocation(IList<ParameterBinding> inputData)
6065
inputData.First(item => item.Name == _durableFunctionInfo.DurableClientBindingName)
6166
.Data.ToObject();
6267

63-
this.pwsh.AddCommand("Import-Module")
64-
.AddParameter("Name", "DurableSDK")
65-
.InvokeAndClearCommands<Action<object>>();
66-
67-
//this.pwsh.AddCommand("Import-Module")
68-
// .AddParameter("Name", "C:\\Users\\dajusto\\source\\repos\\azure-functions-durable-powershell-private\\samples\\durableApp\\Modules\\DurableSDK\\bin\\Debug\\net6.0\\DurableSDK.dll")
69-
// .InvokeAndClearCommands<Action<object>>();
70-
71-
//this.pwsh.AddCommand("Set-BindingData")
72-
// .AddParameter("Input", "")
73-
// .InvokeAndClearCommands<Action<object>>();
74-
7568
_powerShellServices.SetDurableClient(durableClient);
7669

7770
}
@@ -122,26 +115,17 @@ public bool TryGetInputBindingParameterValue(string bindingName, out object valu
122115

123116
public void AddPipelineOutputIfNecessary(Collection<object> pipelineItems, Hashtable result)
124117
{
125-
var shouldAddPipelineOutput =
126-
_durableFunctionInfo.Type == DurableFunctionType.ActivityFunction;
127-
128-
if (shouldAddPipelineOutput)
118+
119+
if (ShouldSuppressPipelineTraces())
129120
{
130121
var returnValue = FunctionReturnValueBuilder.CreateReturnValueFromFunctionOutput(pipelineItems);
131122
result.Add(AzFunctionInfo.DollarReturn, returnValue);
132123
}
133124
}
134125

135-
public bool TryInvokeOrchestrationFunction(out Hashtable result)
126+
public Hashtable InvokeOrchestrationFunction()
136127
{
137-
if (!_durableFunctionInfo.IsOrchestrationFunction)
138-
{
139-
result = null;
140-
return false;
141-
}
142-
143-
result = _orchestrationInvoker.Invoke(_orchestrationBindingInfo, _powerShellServices);
144-
return true;
128+
return _orchestrationInvoker.Invoke(_orchestrationBindingInfo, _powerShellServices);
145129
}
146130

147131
public bool ShouldSuppressPipelineTraces()

src/PowerShell/PowerShellManager.cs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
namespace Microsoft.Azure.Functions.PowerShellWorker.PowerShell
1717
{
18+
using Microsoft.Azure.Functions.PowerShellWorker.DurableWorker;
1819
using System.Management.Automation;
1920
using System.Text;
2021

@@ -204,27 +205,38 @@ public Hashtable InvokeFunction(
204205
FunctionInvocationPerformanceStopwatch stopwatch)
205206
{
206207
var outputBindings = FunctionMetadata.GetOutputBindingHashtable(_pwsh.Runspace.InstanceId);
207-
var durableController = new DurableController(functionInfo.DurableFunctionInfo, _pwsh);
208+
var durableFunctionsUtils = new DurableController(functionInfo.DurableFunctionInfo, _pwsh);
208209

209210
try
210211
{
211-
212-
durableController.BeforeFunctionInvocation(inputData);
212+
durableFunctionsUtils.InitializeBindings(inputData);
213213

214214
AddEntryPointInvocationCommand(functionInfo);
215215
stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.FunctionCodeReady);
216216

217-
SetInputBindingParameterValues(functionInfo, inputData, durableController, triggerMetadata, traceContext, retryContext);
217+
var orchestrationParamName = durableFunctionsUtils.GetOrchestrationParameterName();
218+
SetInputBindingParameterValues(functionInfo, inputData, orchestrationParamName, triggerMetadata, traceContext, retryContext);
218219
stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.InputBindingValuesReady);
219220

220221
stopwatch.OnCheckpoint(FunctionInvocationPerformanceStopwatch.Checkpoint.InvokingFunctionCode);
221222
Logger.Log(isUserOnlyLog: false, LogLevel.Trace, CreateInvocationPerformanceReportMessage(functionInfo.FuncName, stopwatch));
222223

223224
try
224225
{
225-
return durableController.TryInvokeOrchestrationFunction(out var result)
226-
? result
227-
: InvokeNonOrchestrationFunction(durableController, outputBindings);
226+
if(functionInfo.DurableFunctionInfo.IsOrchestrationFunction)
227+
{
228+
return durableFunctionsUtils.InvokeOrchestrationFunction();
229+
}
230+
else
231+
{
232+
var addPipelineOutput = functionInfo.DurableFunctionInfo.Type != DurableFunctionType.ActivityFunction;
233+
if (addPipelineOutput)
234+
{
235+
_pwsh.AddCommand("Microsoft.Azure.Functions.PowerShellWorker\\Trace-PipelineObject");
236+
}
237+
return ExecuteUserCode(addPipelineOutput, outputBindings);
238+
}
239+
228240
}
229241
catch (RuntimeException e)
230242
{
@@ -243,7 +255,8 @@ public Hashtable InvokeFunction(
243255
}
244256
finally
245257
{
246-
durableController.AfterFunctionInvocation();
258+
// TODO: determine if external SDK also needs this call
259+
durableFunctionsUtils.AfterFunctionInvocation();
247260
outputBindings.Clear();
248261
ResetRunspace();
249262
}
@@ -252,7 +265,7 @@ public Hashtable InvokeFunction(
252265
private void SetInputBindingParameterValues(
253266
AzFunctionInfo functionInfo,
254267
IEnumerable<ParameterBinding> inputData,
255-
DurableController durableController,
268+
string orchParamName,
256269
Hashtable triggerMetadata,
257270
TraceContext traceContext,
258271
RetryContext retryContext)
@@ -261,10 +274,10 @@ private void SetInputBindingParameterValues(
261274
{
262275
if (functionInfo.FuncParameters.TryGetValue(binding.Name, out var paramInfo))
263276
{
264-
if (!durableController.TryGetInputBindingParameterValue(binding.Name, out var valueToUse))
277+
if (string.CompareOrdinal(binding.Name, orchParamName) != 0)
265278
{
266279
var bindingInfo = functionInfo.InputBindings[binding.Name];
267-
valueToUse = Utils.TransformInBindingValueAsNeeded(paramInfo, bindingInfo, binding.Data.ToObject());
280+
var valueToUse = Utils.TransformInBindingValueAsNeeded(paramInfo, bindingInfo, binding.Data.ToObject());
268281
_pwsh.AddParameter(binding.Name, valueToUse);
269282
}
270283
else
@@ -297,11 +310,15 @@ private void SetInputBindingParameterValues(
297310
/// <summary>
298311
/// Execution a function fired by a trigger or an activity function scheduled by an orchestration.
299312
/// </summary>
300-
private Hashtable InvokeNonOrchestrationFunction(DurableController durableController, IDictionary outputBindings)
313+
private Hashtable ExecuteUserCode(bool addPipelineOutput, IDictionary outputBindings)
301314
{
302315
var pipelineItems = _pwsh.InvokeAndClearCommands<object>();
303316
var result = new Hashtable(outputBindings, StringComparer.OrdinalIgnoreCase);
304-
durableController.AddPipelineOutputIfNecessary(pipelineItems, result);
317+
if (addPipelineOutput)
318+
{
319+
var returnValue = FunctionReturnValueBuilder.CreateReturnValueFromFunctionOutput(pipelineItems);
320+
result.Add(AzFunctionInfo.DollarReturn, returnValue);
321+
}
305322
return result;
306323
}
307324

test/Unit/Durable/DurableControllerTests.cs

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public void BeforeFunctionInvocation_SetsDurableClient_ForDurableClientFunction(
3939

4040
_mockPowerShellServices.Setup(_ => _.SetDurableClient(It.IsAny<object>()));
4141

42-
durableController.BeforeFunctionInvocation(inputData);
42+
durableController.InitializeBindings(inputData);
4343

4444
_mockPowerShellServices.Verify(
4545
_ => _.SetDurableClient(
@@ -60,7 +60,7 @@ public void BeforeFunctionInvocation_SetsOrchestrationContext_ForOrchestrationFu
6060

6161
_mockPowerShellServices.Setup(_ => _.SetOrchestrationContext(It.IsAny<OrchestrationContext>()));
6262

63-
durableController.BeforeFunctionInvocation(inputData);
63+
durableController.InitializeBindings(inputData);
6464

6565
_mockPowerShellServices.Verify(
6666
_ => _.SetOrchestrationContext(
@@ -74,7 +74,7 @@ public void BeforeFunctionInvocation_Throws_OnOrchestrationFunctionWithoutContex
7474
var durableController = CreateDurableController(DurableFunctionType.OrchestrationFunction);
7575
var inputData = new ParameterBinding[0];
7676

77-
Assert.ThrowsAny<ArgumentException>(() => durableController.BeforeFunctionInvocation(inputData));
77+
Assert.ThrowsAny<ArgumentException>(() => durableController.InitializeBindings(inputData));
7878
}
7979

8080
[Theory]
@@ -91,7 +91,7 @@ internal void BeforeFunctionInvocation_DoesNothing_ForNonOrchestrationFunction(D
9191
CreateParameterBinding("ParameterName", orchestrationContext)
9292
};
9393

94-
durableController.BeforeFunctionInvocation(inputData);
94+
durableController.InitializeBindings(inputData);
9595
}
9696

9797
[Theory]
@@ -121,7 +121,7 @@ public void TryGetInputBindingParameterValue_RetrievesOrchestrationContextParame
121121
};
122122

123123
_mockPowerShellServices.Setup(_ => _.SetOrchestrationContext(It.IsAny<OrchestrationContext>()));
124-
durableController.BeforeFunctionInvocation(inputData);
124+
durableController.InitializeBindings(inputData);
125125

126126
Assert.True(durableController.TryGetInputBindingParameterValue(contextParameterName, out var value));
127127
Assert.Equal(orchestrationContext.InstanceId, ((OrchestrationContext)value).InstanceId);
@@ -142,7 +142,7 @@ internal void TryGetInputBindingParameterValue_RetrievesNothing_ForNonOrchestrat
142142
};
143143

144144
_mockPowerShellServices.Setup(_ => _.SetOrchestrationContext(It.IsAny<OrchestrationContext>()));
145-
durableController.BeforeFunctionInvocation(inputData);
145+
durableController.InitializeBindings(inputData);
146146

147147
Assert.False(durableController.TryGetInputBindingParameterValue(contextParameterName, out var value));
148148
Assert.Null(value);
@@ -158,15 +158,14 @@ public void TryInvokeOrchestrationFunction_InvokesOrchestrationFunction()
158158
var durableController = CreateDurableController(DurableFunctionType.OrchestrationFunction);
159159

160160
_mockPowerShellServices.Setup(_ => _.SetOrchestrationContext(It.IsAny<OrchestrationContext>()));
161-
durableController.BeforeFunctionInvocation(inputData);
161+
durableController.InitializeBindings(inputData);
162162

163163
var expectedResult = new Hashtable();
164164
_mockOrchestrationInvoker.Setup(
165165
_ => _.Invoke(It.IsAny<OrchestrationBindingInfo>(), It.IsAny<IPowerShellServices>()))
166166
.Returns(expectedResult);
167167

168-
var invoked = durableController.TryInvokeOrchestrationFunction(out var actualResult);
169-
Assert.True(invoked);
168+
var actualResult = durableController.InvokeOrchestrationFunction();
170169
Assert.Same(expectedResult, actualResult);
171170

172171
_mockOrchestrationInvoker.Verify(
@@ -178,25 +177,6 @@ public void TryInvokeOrchestrationFunction_InvokesOrchestrationFunction()
178177
Times.Once);
179178
}
180179

181-
[Theory]
182-
[InlineData(DurableFunctionType.None)]
183-
[InlineData(DurableFunctionType.ActivityFunction)]
184-
internal void TryInvokeOrchestrationFunction_DoesNotInvokeNonOrchestrationFunction(DurableFunctionType durableFunctionType)
185-
{
186-
var contextParameterName = "ParameterName";
187-
var orchestrationContext = new OrchestrationContext { InstanceId = Guid.NewGuid().ToString() };
188-
var inputData = new[] { CreateParameterBinding(contextParameterName, orchestrationContext) };
189-
190-
var durableController = CreateDurableController(durableFunctionType);
191-
192-
_mockPowerShellServices.Setup(_ => _.SetOrchestrationContext(It.IsAny<OrchestrationContext>()));
193-
durableController.BeforeFunctionInvocation(inputData);
194-
195-
var invoked = durableController.TryInvokeOrchestrationFunction(out var actualResult);
196-
Assert.False(invoked);
197-
Assert.Null(actualResult);
198-
}
199-
200180
[Fact]
201181
public void AddPipelineOutputIfNecessary_AddsDollarReturn_ForActivityFunction()
202182
{

test/Unit/Durable/OrchestrationInvokerTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public void InvocationRunsToCompletionIfNotStopped()
4040
_mockPowerShellServices.Verify(_ => _.BeginInvoke(It.IsAny<PSDataCollection<object>>()), Times.Once);
4141
_mockPowerShellServices.Verify(_ => _.EndInvoke(invocationAsyncResult), Times.Once);
4242
_mockPowerShellServices.Verify(_ => _.ClearStreamsAndCommands(), Times.Once);
43+
_mockPowerShellServices.Verify(_ => _.TracePipelineObject(), Times.Once);
44+
_mockPowerShellServices.Verify(_ => _.AddParameter(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
4345
_mockPowerShellServices.VerifyNoOtherCalls();
4446
}
4547

@@ -51,6 +53,8 @@ public void InvocationStopsOnStopEvent()
5153
_mockPowerShellServices.Verify(_ => _.BeginInvoke(It.IsAny<PSDataCollection<object>>()), Times.Once);
5254
_mockPowerShellServices.Verify(_ => _.StopInvoke(), Times.Once);
5355
_mockPowerShellServices.Verify(_ => _.ClearStreamsAndCommands(), Times.Once);
56+
_mockPowerShellServices.Verify(_ => _.TracePipelineObject(), Times.Once);
57+
_mockPowerShellServices.Verify(_ => _.AddParameter(It.IsAny<string>(), It.IsAny<object>()), Times.Once);
5458
_mockPowerShellServices.VerifyNoOtherCalls();
5559
}
5660

0 commit comments

Comments
 (0)