From fe1dfee7bb5a34421dfc9ee591f968461d5568e1 Mon Sep 17 00:00:00 2001 From: Marie Hoeger Date: Tue, 3 Dec 2019 19:12:22 -0800 Subject: [PATCH] do not use placeholder worker if ~3 and v2 compatability enabled (#5328) * do not use placeholder worker if ~3 and v2 compatability enabled * delete irrelevant comment --- .../Environment/EnvironmentExtensions.cs | 11 +++++++++ .../Rpc/WebHostRpcWorkerChannelManager.cs | 4 +++- .../WebHostRpcWorkerChannelManagerTests.cs | 23 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/WebJobs.Script/Environment/EnvironmentExtensions.cs b/src/WebJobs.Script/Environment/EnvironmentExtensions.cs index 4f2f43fe6e..a6b43bef91 100644 --- a/src/WebJobs.Script/Environment/EnvironmentExtensions.cs +++ b/src/WebJobs.Script/Environment/EnvironmentExtensions.cs @@ -108,6 +108,17 @@ public static bool IsV2CompatibilityMode(this IEnvironment environment) return isFunctionsV2CompatibilityMode || isV2ExtensionVersion; } + public static bool IsV2CompatabileOnV3Extension(this IEnvironment environment) + { + string compatModeString = environment.GetEnvironmentVariable(FunctionsV2CompatibilityModeKey); + bool.TryParse(compatModeString, out bool isFunctionsV2CompatibilityMode); + + string extensionVersion = environment.GetEnvironmentVariable(FunctionsExtensionVersion); + bool isV3ExtensionVersion = string.Compare(extensionVersion, "~3", CultureInfo.InvariantCulture, CompareOptions.OrdinalIgnoreCase) == 0; + + return isFunctionsV2CompatibilityMode && isV3ExtensionVersion; + } + public static bool IsContainer(this IEnvironment environment) { var runningInContainer = environment.GetEnvironmentVariable(RunningInContainer); diff --git a/src/WebJobs.Script/Workers/Rpc/WebHostRpcWorkerChannelManager.cs b/src/WebJobs.Script/Workers/Rpc/WebHostRpcWorkerChannelManager.cs index cf47f9db10..08ccc13036 100644 --- a/src/WebJobs.Script/Workers/Rpc/WebHostRpcWorkerChannelManager.cs +++ b/src/WebJobs.Script/Workers/Rpc/WebHostRpcWorkerChannelManager.cs @@ -133,10 +133,12 @@ private bool UsePlaceholderChannel(string workerRuntime) if (!string.IsNullOrEmpty(workerRuntime)) { // Special case: node apps must be read-only to use the placeholder mode channel + // Also cannot use placeholder worker that is targeting ~3 but has backwards compatibility with V2 enabled // TODO: Remove special casing when resolving https://github.com/Azure/azure-functions-host/issues/4534 if (string.Equals(workerRuntime, RpcWorkerConstants.NodeLanguageWorkerName, StringComparison.OrdinalIgnoreCase)) { - return _environment.IsFileSystemReadOnly(); + // Use if readonly and not v2 compatible on ~3 extension + return _environment.IsFileSystemReadOnly() && !_environment.IsV2CompatabileOnV3Extension(); } return true; } diff --git a/test/WebJobs.Script.Tests/Workers/Rpc/WebHostRpcWorkerChannelManagerTests.cs b/test/WebJobs.Script.Tests/Workers/Rpc/WebHostRpcWorkerChannelManagerTests.cs index 9954f59ce4..c69fd961c3 100644 --- a/test/WebJobs.Script.Tests/Workers/Rpc/WebHostRpcWorkerChannelManagerTests.cs +++ b/test/WebJobs.Script.Tests/Workers/Rpc/WebHostRpcWorkerChannelManagerTests.cs @@ -258,6 +258,29 @@ public async Task SpecializeAsync_Node_NotReadOnly_KillsProcess() Assert.Null(initializedChannel); } + [Fact] + public async Task SpecializeAsync_Node_V2CompatibilityWithV3Extension_KillsProcess() + { + var testMetricsLogger = new TestMetricsLogger(); + _testEnvironment.SetEnvironmentVariable(RpcWorkerConstants.FunctionWorkerRuntimeSettingName, RpcWorkerConstants.NodeLanguageWorkerName); + _testEnvironment.SetEnvironmentVariable(EnvironmentSettingNames.FunctionsV2CompatibilityModeKey, "true"); + _testEnvironment.SetEnvironmentVariable(EnvironmentSettingNames.FunctionsExtensionVersion, "~3"); + + _rpcWorkerChannelManager = new WebHostRpcWorkerChannelManager(_eventManager, _testEnvironment, _loggerFactory, _rpcWorkerChannelFactory, _optionsMonitor, testMetricsLogger); + + IRpcWorkerChannel nodeWorkerChannel = CreateTestChannel(RpcWorkerConstants.NodeLanguageWorkerName); + + await _rpcWorkerChannelManager.SpecializeAsync(); + + // Verify logs + var traces = _testLogger.GetLogMessages(); + Assert.True(traces.Count() == 0); + + // Verify channel + var initializedChannel = await _rpcWorkerChannelManager.GetChannelAsync(RpcWorkerConstants.NodeLanguageWorkerName); + Assert.Null(initializedChannel); + } + [Fact] public async Task ShutdownStandbyChannels_WorkerRuntime_Not_Set() {