From 8b250683654e7f3431239aaf19a75dac0277dde8 Mon Sep 17 00:00:00 2001 From: Michael Peng Date: Mon, 14 Mar 2022 14:04:32 -0700 Subject: [PATCH 1/5] Define a contract for the external invoker --- test/Unit/Durable/DurableControllerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Unit/Durable/DurableControllerTests.cs b/test/Unit/Durable/DurableControllerTests.cs index e16f04d7..ad4dca14 100644 --- a/test/Unit/Durable/DurableControllerTests.cs +++ b/test/Unit/Durable/DurableControllerTests.cs @@ -26,6 +26,7 @@ public class DurableControllerTests private const string _contextParameterName = "ParameterName"; private static readonly OrchestrationContext _orchestrationContext = new OrchestrationContext { InstanceId = Guid.NewGuid().ToString() }; private static readonly OrchestrationBindingInfo _orchestrationBindingInfo = new OrchestrationBindingInfo(_contextParameterName, _orchestrationContext); + private readonly Mock _mockExternalInvoker = new Mock(MockBehavior.Strict); [Fact] public void InitializeBindings_SetsDurableClient_ForDurableClientFunction() @@ -119,7 +120,6 @@ public void TryGetInputBindingParameterValue_RetrievesOrchestrationContextParame { CreateParameterBinding(_contextParameterName, _orchestrationContext) }; - _mockPowerShellServices.Setup(_ => _.SetOrchestrationContext( It.IsAny(), out It.Ref.IsAny)) From b0f1cbeaf78a5867fd4e7e2fa3f5fc8f12dcee42 Mon Sep 17 00:00:00 2001 From: Michael Peng Date: Mon, 14 Mar 2022 16:47:37 -0700 Subject: [PATCH 2/5] Remove extraneous comments and variables --- test/Unit/Durable/DurableControllerTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Unit/Durable/DurableControllerTests.cs b/test/Unit/Durable/DurableControllerTests.cs index ad4dca14..b57cb767 100644 --- a/test/Unit/Durable/DurableControllerTests.cs +++ b/test/Unit/Durable/DurableControllerTests.cs @@ -26,7 +26,6 @@ public class DurableControllerTests private const string _contextParameterName = "ParameterName"; private static readonly OrchestrationContext _orchestrationContext = new OrchestrationContext { InstanceId = Guid.NewGuid().ToString() }; private static readonly OrchestrationBindingInfo _orchestrationBindingInfo = new OrchestrationBindingInfo(_contextParameterName, _orchestrationContext); - private readonly Mock _mockExternalInvoker = new Mock(MockBehavior.Strict); [Fact] public void InitializeBindings_SetsDurableClient_ForDurableClientFunction() From 927541413849b1d2455aaa29d833a1f88539b811 Mon Sep 17 00:00:00 2001 From: Michael Peng Date: Wed, 16 Mar 2022 12:38:59 -0700 Subject: [PATCH 3/5] Allow worker to read results directly from the external SDK --- src/DurableSDK/ExternalInvoker.cs | 9 ++++----- src/DurableSDK/IExternalInvoker.cs | 4 +++- src/DurableSDK/OrchestrationContext.cs | 12 ------------ src/DurableSDK/OrchestrationInvoker.cs | 18 +++--------------- src/DurableSDK/PowerShellServices.cs | 3 +-- 5 files changed, 11 insertions(+), 35 deletions(-) diff --git a/src/DurableSDK/ExternalInvoker.cs b/src/DurableSDK/ExternalInvoker.cs index f0a73b86..fa8a31c6 100644 --- a/src/DurableSDK/ExternalInvoker.cs +++ b/src/DurableSDK/ExternalInvoker.cs @@ -6,22 +6,21 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.Durable { using System; + using System.Collections; using System.Management.Automation; internal class ExternalInvoker : IExternalInvoker { private readonly Func _externalSDKInvokerFunction; - private readonly IPowerShellServices _powerShellServices; - public ExternalInvoker(Func invokerFunction, IPowerShellServices powerShellServices) + public ExternalInvoker(Func invokerFunction) { _externalSDKInvokerFunction = invokerFunction; - _powerShellServices = powerShellServices; } - public void Invoke() + public Hashtable Invoke(IPowerShellServices powerShellServices) { - _externalSDKInvokerFunction.Invoke(_powerShellServices.GetPowerShell()); + return (Hashtable)_externalSDKInvokerFunction.Invoke(powerShellServices.GetPowerShell()); } } } diff --git a/src/DurableSDK/IExternalInvoker.cs b/src/DurableSDK/IExternalInvoker.cs index 16d17e23..3a703f3d 100644 --- a/src/DurableSDK/IExternalInvoker.cs +++ b/src/DurableSDK/IExternalInvoker.cs @@ -5,10 +5,12 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.Durable { + using System.Collections; + // Represents a contract for the internal interface IExternalInvoker { // Method to invoke an orchestration using the external Durable SDK - void Invoke(); + Hashtable Invoke(IPowerShellServices powerShellServices); } } diff --git a/src/DurableSDK/OrchestrationContext.cs b/src/DurableSDK/OrchestrationContext.cs index e7edec60..27f082db 100644 --- a/src/DurableSDK/OrchestrationContext.cs +++ b/src/DurableSDK/OrchestrationContext.cs @@ -35,18 +35,6 @@ public class OrchestrationContext internal OrchestrationActionCollector OrchestrationActionCollector { get; } = new OrchestrationActionCollector(); - internal object ExternalSDKResult; - - internal bool ExternalSDKIsError; - - // Called by the External DF SDK to communicate its orchestration result - // back to the worker. - internal void SetExternalResult(object result, bool isError) - { - this.ExternalSDKResult = result; - this.ExternalSDKIsError = isError; - } - internal object CustomStatus { get; set; } } } diff --git a/src/DurableSDK/OrchestrationInvoker.cs b/src/DurableSDK/OrchestrationInvoker.cs index 4706c2c3..cb42f212 100644 --- a/src/DurableSDK/OrchestrationInvoker.cs +++ b/src/DurableSDK/OrchestrationInvoker.cs @@ -25,7 +25,7 @@ public Hashtable Invoke( { if (powerShellServices.UseExternalDurableSDK()) { - return InvokeExternalDurableSDK(orchestrationBindingInfo, powerShellServices); + return InvokeExternalDurableSDK(powerShellServices); } return InvokeInternalDurableSDK(orchestrationBindingInfo, powerShellServices); } @@ -35,22 +35,10 @@ public Hashtable Invoke( } } - public Hashtable InvokeExternalDurableSDK( - OrchestrationBindingInfo orchestrationBindingInfo, - IPowerShellServices powerShellServices) + public Hashtable InvokeExternalDurableSDK(IPowerShellServices powerShellServices) { - _externalInvoker.Invoke(); - var result = orchestrationBindingInfo.Context.ExternalSDKResult; - var isError = orchestrationBindingInfo.Context.ExternalSDKIsError; - if (isError) - { - throw (Exception)result; - } - else - { - return (Hashtable)result; - } + return _externalInvoker.Invoke(powerShellServices); } public Hashtable InvokeInternalDurableSDK( diff --git a/src/DurableSDK/PowerShellServices.cs b/src/DurableSDK/PowerShellServices.cs index 2a403c1a..549d4417 100644 --- a/src/DurableSDK/PowerShellServices.cs +++ b/src/DurableSDK/PowerShellServices.cs @@ -99,11 +99,10 @@ public OrchestrationBindingInfo SetOrchestrationContext( // The external SetFunctionInvocationContextCommand expects a .json string to deserialize // and writes an invoker function to the output pipeline. .AddParameter("OrchestrationContext", context.Data.String) - .AddParameter("SetResult", (Action) orchestrationBindingInfo.Context.SetExternalResult) .InvokeAndClearCommands>(); if (output.Count() == 1) { - externalInvoker = new ExternalInvoker(output[0], this); + externalInvoker = new ExternalInvoker(output[0]); } else { From 7e05eb9d3ff841f1c5428909cd2f21d8d7cd81e9 Mon Sep 17 00:00:00 2001 From: David Justo Date: Thu, 17 Mar 2022 09:48:14 -0700 Subject: [PATCH 4/5] generalize try-catch behavior for ORchestrationFailure exceptions --- src/DurableSDK/OrchestrationInvoker.cs | 8 +++++++- src/PowerShell/PowerShellManager.cs | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/DurableSDK/OrchestrationInvoker.cs b/src/DurableSDK/OrchestrationInvoker.cs index cb42f212..e0ac93e6 100644 --- a/src/DurableSDK/OrchestrationInvoker.cs +++ b/src/DurableSDK/OrchestrationInvoker.cs @@ -16,6 +16,7 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.Durable internal class OrchestrationInvoker : IOrchestrationInvoker { private IExternalInvoker _externalInvoker; + internal static string isOrchestrationFailureKey = "IsOrchestrationFailure"; public Hashtable Invoke( OrchestrationBindingInfo orchestrationBindingInfo, @@ -29,6 +30,11 @@ public Hashtable Invoke( } return InvokeInternalDurableSDK(orchestrationBindingInfo, powerShellServices); } + catch (Exception ex) + { + ex.Data.Add(isOrchestrationFailureKey, true); + throw; + } finally { powerShellServices.ClearStreamsAndCommands(); @@ -37,7 +43,6 @@ public Hashtable Invoke( public Hashtable InvokeExternalDurableSDK(IPowerShellServices powerShellServices) { - return _externalInvoker.Invoke(powerShellServices); } @@ -87,6 +92,7 @@ public Hashtable InvokeInternalDurableSDK( // this should be treated as an entire orchestration failure throw new OrchestrationFailureException(actions, context.CustomStatus, e); } + } } diff --git a/src/PowerShell/PowerShellManager.cs b/src/PowerShell/PowerShellManager.cs index c604da81..0344c05d 100644 --- a/src/PowerShell/PowerShellManager.cs +++ b/src/PowerShell/PowerShellManager.cs @@ -243,9 +243,9 @@ public Hashtable InvokeFunction( Logger.Log(isUserOnlyLog: true, LogLevel.Error, GetFunctionExceptionMessage(e)); throw; } - catch (OrchestrationFailureException e) + catch (Exception e) { - if (e.InnerException is IContainsErrorRecord inner) + if (e.Data.Contains(OrchestrationInvoker.isOrchestrationFailureKey) && e.InnerException is IContainsErrorRecord inner) { Logger.Log(isUserOnlyLog: true, LogLevel.Error, GetFunctionExceptionMessage(inner)); } From 86b5df163be604d77a2ff3415f787fe613ab08f0 Mon Sep 17 00:00:00 2001 From: David Justo Date: Thu, 17 Mar 2022 10:02:59 -0700 Subject: [PATCH 5/5] remove extra line --- src/DurableSDK/OrchestrationInvoker.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DurableSDK/OrchestrationInvoker.cs b/src/DurableSDK/OrchestrationInvoker.cs index e0ac93e6..b71116b4 100644 --- a/src/DurableSDK/OrchestrationInvoker.cs +++ b/src/DurableSDK/OrchestrationInvoker.cs @@ -92,7 +92,6 @@ public Hashtable InvokeInternalDurableSDK( // this should be treated as an entire orchestration failure throw new OrchestrationFailureException(actions, context.CustomStatus, e); } - } }