diff --git a/Kudu.Core/Functions/KedaFunctionTriggerProvider.cs b/Kudu.Core/Functions/KedaFunctionTriggerProvider.cs index 1fc58b05..332f5f0b 100644 --- a/Kudu.Core/Functions/KedaFunctionTriggerProvider.cs +++ b/Kudu.Core/Functions/KedaFunctionTriggerProvider.cs @@ -106,8 +106,8 @@ string ReplaceMatchedBindingExpression(Match match) public static IEnumerable GetFunctionTriggers(IEnumerable functionsJson, string hostJsonText, IDictionary appSettings) { var triggerBindings = functionsJson - .Select(o => ParseFunctionJson(o["functionName"]?.ToString(), o)) - .SelectMany(i => i); + .Select(o => ParseFunctionJson(o["functionName"]?.ToString(), o)) + .SelectMany(i => i); return CreateScaleTriggers(triggerBindings, hostJsonText, appSettings); } diff --git a/Kudu.Tests/Core/Function/KedaFunctionTriggersProviderTests.cs b/Kudu.Tests/Core/Function/KedaFunctionTriggersProviderTests.cs index cd0e784c..a5b2209a 100644 --- a/Kudu.Tests/Core/Function/KedaFunctionTriggersProviderTests.cs +++ b/Kudu.Tests/Core/Function/KedaFunctionTriggersProviderTests.cs @@ -12,7 +12,7 @@ namespace Kudu.Tests.Core.Function public class KedaFunctionTriggersProviderTests { [Fact] - public void DurableFunctionApp() + public void DurableFunctions_DeployAsZip() { // Generate a zip archive with a host.json and the contents of a Durable Function app string zipFilePath = Path.GetTempFileName(); @@ -30,26 +30,7 @@ public void DurableFunctionApp() try { IEnumerable result = KedaFunctionTriggerProvider.GetFunctionTriggers(zipFilePath); - Assert.Equal(3, result.Count()); - - ScaleTrigger mssqlTrigger = Assert.Single(result, trigger => trigger.Type.Equals("mssql", StringComparison.OrdinalIgnoreCase)); - string query = Assert.Contains("query", mssqlTrigger.Metadata); - Assert.False(string.IsNullOrEmpty(query)); - - string targetValue = Assert.Contains("targetValue", mssqlTrigger.Metadata); - Assert.False(string.IsNullOrEmpty(targetValue)); - Assert.True(double.TryParse(targetValue, out _)); - - string connectionStringName = Assert.Contains("connectionStringFromEnv", mssqlTrigger.Metadata); - Assert.Equal("SQLDB_Connection", connectionStringName); - - ScaleTrigger queueTrigger = Assert.Single(result, trigger => trigger.Type.Equals("azure-queue", StringComparison.OrdinalIgnoreCase)); - string functionName = Assert.Contains("functionName", queueTrigger.Metadata); - Assert.Equal("f4", functionName); - - ScaleTrigger httpTrigger = Assert.Single(result, trigger => trigger.Type.Equals("httpTrigger", StringComparison.OrdinalIgnoreCase)); - functionName = Assert.Contains("functionName", httpTrigger.Metadata); - Assert.Equal("f5", functionName); + ValidateDurableTriggers(result); } finally { @@ -57,6 +38,31 @@ public void DurableFunctionApp() } } + internal static void ValidateDurableTriggers(IEnumerable triggers) + { + Assert.Equal(3, triggers.Count()); + + ScaleTrigger mssqlTrigger = Assert.Single(triggers, trigger => trigger.Type.Equals("mssql", StringComparison.OrdinalIgnoreCase)); + string query = Assert.Contains("query", mssqlTrigger.Metadata); + Assert.NotNull(query); + Assert.Contains("dt.GetScaleRecommendation", query); + + string targetValue = Assert.Contains("targetValue", mssqlTrigger.Metadata); + Assert.False(string.IsNullOrEmpty(targetValue)); + Assert.True(double.TryParse(targetValue, out _)); + + string connectionStringName = Assert.Contains("connectionStringFromEnv", mssqlTrigger.Metadata); + Assert.Equal("SQLDB_Connection", connectionStringName); + + ScaleTrigger queueTrigger = Assert.Single(triggers, trigger => trigger.Type.Equals("azure-queue", StringComparison.OrdinalIgnoreCase)); + string functionName = Assert.Contains("functionName", queueTrigger.Metadata); + Assert.Equal("f4", functionName); + + ScaleTrigger httpTrigger = Assert.Single(triggers, trigger => trigger.Type.Equals("httpTrigger", StringComparison.OrdinalIgnoreCase)); + functionName = Assert.Contains("functionName", httpTrigger.Metadata); + Assert.Equal("f5", functionName); + } + [Theory] [InlineData("flowc1712a574433c1djobtriggers00", "10", "haassyad-scaling-lima", "workflowApp", @"{""version"":""2.0"",""extensionBundle"":{""id"": ""Microsoft.Azure.Functions.ExtensionBundle.Workflows"", ""version"": ""[1.*, 2.0.0)""}, ""extensions"":{""workflow"":{""Settings"":{""Runtime.ScaleMonitor.KEDA.TargetQueueLength"":10}}}}")] [InlineData("flowdc234f1fbd9ff3fjobtriggers00", "20", "n/a", "workflowApp,functionapp", @"{""version"":""2.0"",""extensionBundle"":{""id"": ""Microsoft.Azure.Functions.ExtensionBundle.Workflows"", ""version"": ""[1.*, 2.0.0)""}, ""extensions"":{""workflow"":{""Settings"":{""Runtime.HostId"":""haassyad-applicationinsights""}}}}")] diff --git a/Kudu.Tests/Core/Function/SyncTriggerHandlerTests.cs b/Kudu.Tests/Core/Function/SyncTriggerHandlerTests.cs index bd3ef022..cee1783c 100644 --- a/Kudu.Tests/Core/Function/SyncTriggerHandlerTests.cs +++ b/Kudu.Tests/Core/Function/SyncTriggerHandlerTests.cs @@ -1,5 +1,8 @@ -using Kudu.Core.Functions; +using System; +using System.Collections.Generic; using System.Linq; +using Kudu.Core.Functions; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Xunit; @@ -24,5 +27,29 @@ public void GetScaleTriggersTest(string functionTriggerPayload) Assert.True(scaleTriggers != null && scaleTriggers.Item1 != null && scaleTriggers.Item1.ToList().Count > 0); } } + + [Fact] + public void DurableFunctions_SyncTriggers() + { + // NOTE: Same basic inputs as KedaFunctionTriggersProviderTests.DurableFunctionsApp + JObject syncTriggersPayloadJson = new JObject( + new JProperty("extensions", JObject.Parse(@"{""durableTask"":{""hubName"":""DFTest"",""storageProvider"":{""type"":""mssql"",""connectionStringName"":""SQLDB_Connection""}}}")), + new JProperty("triggers", new JArray( + JObject.Parse(@"{""functionName"":""f1"",""type"":""orchestrationTrigger"",""name"":""context""}"), + JObject.Parse(@"{""functionName"":""f2"",""type"":""entityTrigger"",""name"":""ctx""}"), + JObject.Parse(@"{""functionName"":""f3"",""type"":""activityTrigger"",""name"":""input""}"), + JObject.Parse(@"{""functionName"":""f4"",""type"":""queueTrigger"",""connection"":""AzureWebjobsStorage"",""queueName"":""queue"",""name"":""queueItem""}"), + JObject.Parse(@"{""functionName"":""f5"",""type"":""httpTrigger"",""methods"":[""post""],""authLevel"":""anonymous"",""name"":""req""}")))); + + string serializedPayload = syncTriggersPayloadJson.ToString(Formatting.None); + + var syncTriggerHandler = new SyncTriggerHandler(null, null, null); + (IEnumerable triggers, string error) = syncTriggerHandler.GetScaleTriggers(serializedPayload); + Assert.Null(error); + Assert.NotNull(triggers); + + // We expect the same output as the other Durable Functions test + KedaFunctionTriggersProviderTests.ValidateDurableTriggers(triggers); + } } }