Skip to content

Commit 5eb137d

Browse files
authored
Do not Initialize language workers for dotnet functions (#3340)
1 parent 6f1d96d commit 5eb137d

File tree

3 files changed

+125
-9
lines changed

3 files changed

+125
-9
lines changed

src/WebJobs.Script/Host/ScriptHost.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public class ScriptHost : JobHost, IScriptJobHost
4949
private readonly IMetricsLogger _metricsLogger = null;
5050
private readonly string _hostLogPath;
5151
private readonly Stopwatch _stopwatch = new Stopwatch();
52-
private readonly string _language;
52+
private readonly string _currentRuntimelanguage;
5353
private readonly IOptions<JobHostOptions> _hostOptions;
5454
private readonly ScriptTypeLocator _typeLocator;
5555
private readonly IDebugStateProvider _debugManager;
@@ -120,7 +120,7 @@ public ScriptHost(IOptions<JobHostOptions> options,
120120

121121
_hostLogPath = Path.Combine(ScriptOptions.RootLogPath, "Host");
122122

123-
_language = _settingsManager.Configuration[LanguageWorkerConstants.FunctionWorkerRuntimeSettingName];
123+
_currentRuntimelanguage = _settingsManager.Configuration[LanguageWorkerConstants.FunctionWorkerRuntimeSettingName];
124124

125125
_loggerFactory = loggerFactory;
126126
_logger = loggerFactory.CreateLogger(LogCategories.Startup);
@@ -251,10 +251,13 @@ public async Task InitializeAsync()
251251
using (_metricsLogger.LatencyEvent(MetricEventNames.HostStartupLatency))
252252
{
253253
PreInitialize();
254-
await InitializeWorkersAsync();
255254

256255
// Generate Functions
257256
IEnumerable<FunctionMetadata> functions = GetFunctionsMetadata();
257+
if (Utility.ShouldInitiliazeLanguageWorkers(functions, _currentRuntimelanguage))
258+
{
259+
await InitializeWorkersAsync();
260+
}
258261
var directTypes = GetDirectTypes(functions);
259262
InitializeFunctionDescriptors(functions);
260263
GenerateFunctions(directTypes);
@@ -430,16 +433,16 @@ private void GenerateFunctions(IEnumerable<Type> directTypes)
430433
/// </summary>
431434
internal void InitializeFunctionDescriptors(IEnumerable<FunctionMetadata> functionMetadata)
432435
{
433-
if (string.IsNullOrEmpty(_language))
436+
if (string.IsNullOrEmpty(_currentRuntimelanguage))
434437
{
435438
_logger.LogTrace("Adding Function descriptor providers for all languages.");
436439
_descriptorProviders.Add(new DotNetFunctionDescriptorProvider(this, ScriptOptions, _bindingProviders, _metricsLogger, _loggerFactory));
437440
_descriptorProviders.Add(new WorkerFunctionDescriptorProvider(this, ScriptOptions, _bindingProviders, _functionDispatcher, _loggerFactory));
438441
}
439442
else
440443
{
441-
_logger.LogTrace($"Adding Function descriptor provider for language {_language}.");
442-
if (string.Equals(_language, LanguageWorkerConstants.DotNetLanguageWorkerName, StringComparison.OrdinalIgnoreCase))
444+
_logger.LogTrace($"Adding Function descriptor provider for language {_currentRuntimelanguage}.");
445+
if (string.Equals(_currentRuntimelanguage, LanguageWorkerConstants.DotNetLanguageWorkerName, StringComparison.OrdinalIgnoreCase))
443446
{
444447
_descriptorProviders.Add(new DotNetFunctionDescriptorProvider(this, ScriptOptions, _bindingProviders, _metricsLogger, _loggerFactory));
445448
}
@@ -496,7 +499,7 @@ private async Task InitializeWorkersAsync()
496499
attemptCount);
497500
};
498501

499-
_functionDispatcher = new FunctionDispatcher(EventManager, server, channelFactory, _workerConfigs, _language);
502+
_functionDispatcher = new FunctionDispatcher(EventManager, server, channelFactory, _workerConfigs, _currentRuntimelanguage);
500503

501504
_eventSubscriptions.Add(EventManager.OfType<WorkerProcessErrorEvent>()
502505
.Subscribe(evt =>
@@ -657,7 +660,7 @@ internal Collection<FunctionDescriptor> GetFunctionDescriptors(IEnumerable<Funct
657660
Collection<FunctionDescriptor> functionDescriptors = new Collection<FunctionDescriptor>();
658661
var httpFunctions = new Dictionary<string, HttpTriggerAttribute>();
659662

660-
if (!Utility.IsSingleLanguage(functions, _language))
663+
if (!Utility.IsSingleLanguage(functions, _currentRuntimelanguage))
661664
{
662665
_logger.LogError($"Found functions with more than one language. Select a language for your function app by specifying {LanguageWorkerConstants.FunctionWorkerRuntimeSettingName} AppSetting");
663666
return functionDescriptors;

src/WebJobs.Script/Utility.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
using System.Text;
1414
using System.Threading;
1515
using System.Threading.Tasks;
16-
using Microsoft.Azure.WebJobs.Host;
1716
using Microsoft.Azure.WebJobs.Script.Config;
17+
using Microsoft.Azure.WebJobs.Script.Description;
18+
using Microsoft.Azure.WebJobs.Script.Rpc;
1819
using Microsoft.Extensions.Logging;
1920
using Newtonsoft.Json;
2021
using Newtonsoft.Json.Converters;
@@ -32,6 +33,7 @@ public static class Utility
3233

3334
private static readonly string UTF8ByteOrderMark = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
3435
private static readonly FilteredExpandoObjectConverter _filteredExpandoObjectConverter = new FilteredExpandoObjectConverter();
36+
private static List<string> dotNetLanguages = new List<string>() { DotNetScriptTypes.CSharp, DotNetScriptTypes.FSharp, DotNetScriptTypes.DotNetAssembly };
3537

3638
/// <summary>
3739
/// Delays while the specified condition remains true.
@@ -447,6 +449,38 @@ internal static bool IsSingleLanguage(IEnumerable<FunctionMetadata> functions, s
447449
return true;
448450
}
449451

452+
internal static bool ShouldInitiliazeLanguageWorkers(IEnumerable<FunctionMetadata> functions, string currentRuntimeLanguage)
453+
{
454+
if (!string.IsNullOrEmpty(currentRuntimeLanguage) && currentRuntimeLanguage.Equals(LanguageWorkerConstants.DotNetLanguageWorkerName, StringComparison.OrdinalIgnoreCase))
455+
{
456+
return false;
457+
}
458+
459+
if (!string.IsNullOrEmpty(currentRuntimeLanguage) && ContainsFunctionWithCurrentLanguage(functions, currentRuntimeLanguage))
460+
{
461+
return true;
462+
}
463+
return ContainsNonDotNetFunctions(functions);
464+
}
465+
466+
private static bool ContainsNonDotNetFunctions(IEnumerable<FunctionMetadata> functions)
467+
{
468+
if (functions != null && functions.Any())
469+
{
470+
return functions.Any(f => !dotNetLanguages.Contains(f.Language, StringComparer.OrdinalIgnoreCase));
471+
}
472+
return false;
473+
}
474+
475+
private static bool ContainsFunctionWithCurrentLanguage(IEnumerable<FunctionMetadata> functions, string currentLanguage)
476+
{
477+
if (functions != null && functions.Any())
478+
{
479+
return functions.Any(f => f.Language.Equals(currentLanguage, StringComparison.OrdinalIgnoreCase));
480+
}
481+
return false;
482+
}
483+
450484
private class FilteredExpandoObjectConverter : ExpandoObjectConverter
451485
{
452486
public override bool CanWrite => true;

test/WebJobs.Script.Tests/ScriptHostTests.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Microsoft.Azure.WebJobs.Script.Config;
1616
using Microsoft.Azure.WebJobs.Script.Description;
1717
using Microsoft.Azure.WebJobs.Script.Eventing;
18+
using Microsoft.Azure.WebJobs.Script.Rpc;
1819
using Microsoft.Extensions.DependencyInjection;
1920
using Microsoft.Extensions.Hosting;
2021
using Microsoft.Extensions.Logging;
@@ -755,6 +756,84 @@ public void IsSingleLanguage_FunctionsList_Null_Returns_False()
755756
Assert.True(Utility.IsSingleLanguage(null, null));
756757
}
757758

759+
[Fact]
760+
public void ShouldInitializeLanguageWorkers_Language_NotSet_Returns_False()
761+
{
762+
Assert.False(Utility.ShouldInitiliazeLanguageWorkers(GetDotNetFunctionsMetadata(), null));
763+
}
764+
765+
[Fact]
766+
public void ShouldInitializeLanguageWorkers_Language_Set_Returns_False()
767+
{
768+
Assert.False(Utility.ShouldInitiliazeLanguageWorkers(GetDotNetFunctionsMetadata(), LanguageWorkerConstants.DotNetLanguageWorkerName));
769+
}
770+
771+
[Fact]
772+
public void ShouldInitializeLanguageWorkers_Language_Set_DotNetFunctions_Returns_False()
773+
{
774+
Assert.False(Utility.ShouldInitiliazeLanguageWorkers(GetDotNetFunctionsMetadata(), LanguageWorkerConstants.NodeLanguageWorkerName));
775+
}
776+
777+
[Fact]
778+
public void ShouldInitializeLanguageWorkers_Language_Set_EmptyFunctions_Returns_False()
779+
{
780+
Assert.False(Utility.ShouldInitiliazeLanguageWorkers(null, LanguageWorkerConstants.NodeLanguageWorkerName));
781+
}
782+
783+
[Fact]
784+
public void ShouldInitializeLanguageWorkers_Language_Set_NodeFunctions_Returns_True()
785+
{
786+
FunctionMetadata funcJs1 = new FunctionMetadata()
787+
{
788+
Name = "funcJs1",
789+
Language = "node"
790+
};
791+
FunctionMetadata funcCS1 = new FunctionMetadata()
792+
{
793+
Name = "funcCS1",
794+
Language = "csharp"
795+
};
796+
IEnumerable<FunctionMetadata> functionsList = new Collection<FunctionMetadata>()
797+
{
798+
funcJs1, funcCS1
799+
};
800+
Assert.True(Utility.ShouldInitiliazeLanguageWorkers(functionsList, LanguageWorkerConstants.NodeLanguageWorkerName));
801+
}
802+
803+
[Fact]
804+
public void ShouldInitializeLanguageWorkers_Language_Not_Set_Returns_True()
805+
{
806+
FunctionMetadata funcJs1 = new FunctionMetadata()
807+
{
808+
Name = "funcJs1",
809+
Language = "node"
810+
};
811+
IEnumerable<FunctionMetadata> functionsList = new Collection<FunctionMetadata>()
812+
{
813+
funcJs1
814+
};
815+
Assert.True(Utility.ShouldInitiliazeLanguageWorkers(functionsList, null));
816+
}
817+
818+
private static IEnumerable<FunctionMetadata> GetDotNetFunctionsMetadata()
819+
{
820+
FunctionMetadata funcCS1 = new FunctionMetadata()
821+
{
822+
Name = "funcCS1",
823+
Language = "csharp"
824+
};
825+
FunctionMetadata funcFS1 = new FunctionMetadata()
826+
{
827+
Name = "funcFs1",
828+
Language = "FSHArp",
829+
};
830+
IEnumerable<FunctionMetadata> functionsList = new Collection<FunctionMetadata>()
831+
{
832+
funcCS1, funcFS1
833+
};
834+
return functionsList;
835+
}
836+
758837
#if WEBROUTING
759838
[Fact]
760839
public void HttpRoutesConflict_ReturnsExpectedResult()

0 commit comments

Comments
 (0)