From 34b08ceb8e7f08591bd906d6506116c14073832f Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Mon, 9 Oct 2023 18:06:17 -0700 Subject: [PATCH 1/6] Handling specialization not supported case. --- .../Grpc/AppPayloadNotFoundException.cs | 12 +++++ .../Grpc/IncomingGrpcMessageHandler.cs | 19 +++++-- host/src/FunctionsNetHost/Grpc/PathUtils.cs | 50 +++++++++---------- .../Grpc/UnsupportedVersionException.cs | 12 +++++ 4 files changed, 63 insertions(+), 30 deletions(-) create mode 100644 host/src/FunctionsNetHost/Grpc/AppPayloadNotFoundException.cs create mode 100644 host/src/FunctionsNetHost/Grpc/UnsupportedVersionException.cs diff --git a/host/src/FunctionsNetHost/Grpc/AppPayloadNotFoundException.cs b/host/src/FunctionsNetHost/Grpc/AppPayloadNotFoundException.cs new file mode 100644 index 000000000..6b9a21e69 --- /dev/null +++ b/host/src/FunctionsNetHost/Grpc/AppPayloadNotFoundException.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Azure.Functions.Worker +{ + public class AppPayloadNotFoundException : Exception + { + public AppPayloadNotFoundException() { } + + public AppPayloadNotFoundException(string message) : base(message) { } + } +} diff --git a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs index bac4f5f42..12173bf4f 100644 --- a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs +++ b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Grpc.Messages; namespace FunctionsNetHost.Grpc @@ -50,16 +51,26 @@ private async Task Process(StreamingMessage msg) Logger.LogTrace("Specialization request received."); var envReloadRequest = msg.FunctionEnvironmentReloadRequest; - var applicationExePath = PathUtils.GetApplicationExePath(envReloadRequest.FunctionAppDirectory); - Logger.LogTrace($"application path {applicationExePath}"); - if (string.IsNullOrWhiteSpace(applicationExePath)) + var workerConfig = PathUtils.GetWorkerConfig(envReloadRequest.FunctionAppDirectory); + + if (workerConfig?.Description is null) { - var ex = new InvalidOperationException($"Unable to find a valid function app payload at '{envReloadRequest.FunctionAppDirectory}'"); + var ex = new AppPayloadNotFoundException($"Unable to find a valid function app payload at '{envReloadRequest.FunctionAppDirectory}'"); responseMessage.FunctionEnvironmentReloadResponse = BuildFailedEnvironmentReloadResponse(ex); break; } + if (!workerConfig.Description.IsSpecializable) + { + var ex = new UnsupportedVersionException("This app is not using the latest version of Microsoft.Azure.Functions.Worker SDK and therefore does not leverage all performance optimizations. See https://aka.ms/azure-functions/dotnet/placeholders for more information."); + responseMessage.FunctionEnvironmentReloadResponse = BuildFailedEnvironmentReloadResponse(ex); + break; + } + + var applicationExePath = workerConfig.Description.DefaultWorkerPath; + Logger.LogTrace($"application path {applicationExePath}"); + foreach (var kv in envReloadRequest.EnvironmentVariables) { EnvironmentUtils.SetValue(kv.Key, kv.Value); diff --git a/host/src/FunctionsNetHost/Grpc/PathUtils.cs b/host/src/FunctionsNetHost/Grpc/PathUtils.cs index 839d79d0d..f79d67229 100644 --- a/host/src/FunctionsNetHost/Grpc/PathUtils.cs +++ b/host/src/FunctionsNetHost/Grpc/PathUtils.cs @@ -2,52 +2,50 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Text.Json; -using System.Text.Json.Nodes; +using System.Text.Json.Serialization; namespace FunctionsNetHost.Grpc { internal static class PathUtils { - /// - /// Gets the absolute path to worker application executable. - /// Builds the path by reading the worker.config.json - /// - /// The FunctionAppDirectory value from environment reload request. - internal static string? GetApplicationExePath(string applicationDirectory) + public static WorkerConfig? GetWorkerConfig(string applicationDirectory) { - string jsonString = string.Empty; string workerConfigPath = string.Empty; + try { workerConfigPath = Path.Combine(applicationDirectory, "worker.config.json"); - jsonString = File.ReadAllText(workerConfigPath); - var workerConfigJsonNode = JsonNode.Parse(jsonString)!; - var executableName = workerConfigJsonNode["description"]?["defaultWorkerPath"]?.ToString(); - - if (executableName == null) + if (!File.Exists(workerConfigPath)) { - Logger.Log($"Invalid worker configuration. description > defaultWorkerPath property value is null. jsonString:{jsonString}"); + Logger.Log($"Worker config file not found at {workerConfigPath}"); return null; } - return Path.Combine(applicationDirectory, executableName); - } - catch (FileNotFoundException ex) - { - Logger.Log($"{workerConfigPath} file not found.{ex}"); - return null; - } - catch (JsonException ex) - { - Logger.Log($"Error parsing JSON in GetApplicationExePath.{ex}. jsonString:{jsonString}"); - return null; + var jsonString = File.ReadAllText(workerConfigPath); + return JsonSerializer.Deserialize(jsonString, WorkerConfigContext.Default.WorkerConfig); } catch (Exception ex) { - Logger.Log($"Error in GetApplicationExePath.{ex}. jsonString:{jsonString}"); + Logger.Log($"Error in GetWorkerConfig.{ex}"); return null; } } } + + public class WorkerDescription + { + public string? DefaultWorkerPath { set; get; } + + public bool IsSpecializable { set; get; } + } + + public class WorkerConfig + { + public WorkerDescription? Description { set; get; } + } + + [JsonSerializable(typeof(WorkerConfig))] + [JsonSourceGenerationOptions(IncludeFields = true, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] + internal partial class WorkerConfigContext : JsonSerializerContext { } } diff --git a/host/src/FunctionsNetHost/Grpc/UnsupportedVersionException.cs b/host/src/FunctionsNetHost/Grpc/UnsupportedVersionException.cs new file mode 100644 index 000000000..061467ee7 --- /dev/null +++ b/host/src/FunctionsNetHost/Grpc/UnsupportedVersionException.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Azure.Functions.Worker +{ + public class UnsupportedVersionException : Exception + { + public UnsupportedVersionException() { } + + public UnsupportedVersionException(string message) : base(message) { } + } +} From 169f6e67cd95509060a250d318ef2f805d112965 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 10 Oct 2023 13:04:51 -0700 Subject: [PATCH 2/6] Handling older worker version for environment reload request. --- .../Grpc/AppPayloadNotFoundException.cs | 12 ----- .../EnvironmentReloadUnsupportedException.cs | 15 ++++++ .../FunctionAppPayloadNotFoundException.cs | 15 ++++++ .../Grpc/IncomingGrpcMessageHandler.cs | 10 ++-- host/src/FunctionsNetHost/Grpc/PathUtils.cs | 51 ------------------- .../Grpc/UnsupportedVersionException.cs | 12 ----- .../Grpc/WorkerConfig/WorkerConfig.cs | 13 +++++ .../WorkerConfigSerializerContext.cs | 11 ++++ .../Grpc/WorkerConfig/WorkerConfigUtils.cs | 36 +++++++++++++ .../Grpc/WorkerConfig/WorkerDescription.cs | 12 +++++ 10 files changed, 107 insertions(+), 80 deletions(-) delete mode 100644 host/src/FunctionsNetHost/Grpc/AppPayloadNotFoundException.cs create mode 100644 host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs create mode 100644 host/src/FunctionsNetHost/Grpc/Exceptions/FunctionAppPayloadNotFoundException.cs delete mode 100644 host/src/FunctionsNetHost/Grpc/PathUtils.cs delete mode 100644 host/src/FunctionsNetHost/Grpc/UnsupportedVersionException.cs create mode 100644 host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfig.cs create mode 100644 host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigSerializerContext.cs create mode 100644 host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigUtils.cs create mode 100644 host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs diff --git a/host/src/FunctionsNetHost/Grpc/AppPayloadNotFoundException.cs b/host/src/FunctionsNetHost/Grpc/AppPayloadNotFoundException.cs deleted file mode 100644 index 6b9a21e69..000000000 --- a/host/src/FunctionsNetHost/Grpc/AppPayloadNotFoundException.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -namespace Microsoft.Azure.Functions.Worker -{ - public class AppPayloadNotFoundException : Exception - { - public AppPayloadNotFoundException() { } - - public AppPayloadNotFoundException(string message) : base(message) { } - } -} diff --git a/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs b/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs new file mode 100644 index 000000000..af0ad0547 --- /dev/null +++ b/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Azure.Functions.Worker +{ + /// + /// The exception that is thrown when the current function app payload does not support environment reload. + /// + public sealed class EnvironmentReloadUnsupportedException : Exception + { + public EnvironmentReloadUnsupportedException() { } + + public EnvironmentReloadUnsupportedException(string message) : base(message) { } + } +} diff --git a/host/src/FunctionsNetHost/Grpc/Exceptions/FunctionAppPayloadNotFoundException.cs b/host/src/FunctionsNetHost/Grpc/Exceptions/FunctionAppPayloadNotFoundException.cs new file mode 100644 index 000000000..97bfac80a --- /dev/null +++ b/host/src/FunctionsNetHost/Grpc/Exceptions/FunctionAppPayloadNotFoundException.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Azure.Functions.Worker +{ + /// + /// The exception that is thrown when there is no function app payload found. + /// + public sealed class FunctionAppPayloadNotFoundException : Exception + { + public FunctionAppPayloadNotFoundException() { } + + public FunctionAppPayloadNotFoundException(string message) : base(message) { } + } +} diff --git a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs index 12173bf4f..58d25e103 100644 --- a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs +++ b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs @@ -52,19 +52,19 @@ private async Task Process(StreamingMessage msg) var envReloadRequest = msg.FunctionEnvironmentReloadRequest; - var workerConfig = PathUtils.GetWorkerConfig(envReloadRequest.FunctionAppDirectory); + var workerConfig = WorkerConfigUtils.GetWorkerConfig(envReloadRequest.FunctionAppDirectory); if (workerConfig?.Description is null) { - var ex = new AppPayloadNotFoundException($"Unable to find a valid function app payload at '{envReloadRequest.FunctionAppDirectory}'"); - responseMessage.FunctionEnvironmentReloadResponse = BuildFailedEnvironmentReloadResponse(ex); + responseMessage.FunctionEnvironmentReloadResponse = BuildFailedEnvironmentReloadResponse(new FunctionAppPayloadNotFoundException()); break; } + // function app payload which uses an older version of Microsoft.Azure.Functions.Worker package does not support specialization. if (!workerConfig.Description.IsSpecializable) { - var ex = new UnsupportedVersionException("This app is not using the latest version of Microsoft.Azure.Functions.Worker SDK and therefore does not leverage all performance optimizations. See https://aka.ms/azure-functions/dotnet/placeholders for more information."); - responseMessage.FunctionEnvironmentReloadResponse = BuildFailedEnvironmentReloadResponse(ex); + Logger.LogTrace("App payload uses an older version of worker package which does not support specialization."); + responseMessage.FunctionEnvironmentReloadResponse = BuildFailedEnvironmentReloadResponse(new EnvironmentReloadUnsupportedException()); break; } diff --git a/host/src/FunctionsNetHost/Grpc/PathUtils.cs b/host/src/FunctionsNetHost/Grpc/PathUtils.cs deleted file mode 100644 index f79d67229..000000000 --- a/host/src/FunctionsNetHost/Grpc/PathUtils.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace FunctionsNetHost.Grpc -{ - internal static class PathUtils - { - public static WorkerConfig? GetWorkerConfig(string applicationDirectory) - { - string workerConfigPath = string.Empty; - - try - { - workerConfigPath = Path.Combine(applicationDirectory, "worker.config.json"); - - if (!File.Exists(workerConfigPath)) - { - Logger.Log($"Worker config file not found at {workerConfigPath}"); - return null; - } - - var jsonString = File.ReadAllText(workerConfigPath); - return JsonSerializer.Deserialize(jsonString, WorkerConfigContext.Default.WorkerConfig); - } - catch (Exception ex) - { - Logger.Log($"Error in GetWorkerConfig.{ex}"); - return null; - } - } - } - - public class WorkerDescription - { - public string? DefaultWorkerPath { set; get; } - - public bool IsSpecializable { set; get; } - } - - public class WorkerConfig - { - public WorkerDescription? Description { set; get; } - } - - [JsonSerializable(typeof(WorkerConfig))] - [JsonSourceGenerationOptions(IncludeFields = true, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] - internal partial class WorkerConfigContext : JsonSerializerContext { } -} diff --git a/host/src/FunctionsNetHost/Grpc/UnsupportedVersionException.cs b/host/src/FunctionsNetHost/Grpc/UnsupportedVersionException.cs deleted file mode 100644 index 061467ee7..000000000 --- a/host/src/FunctionsNetHost/Grpc/UnsupportedVersionException.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -namespace Microsoft.Azure.Functions.Worker -{ - public class UnsupportedVersionException : Exception - { - public UnsupportedVersionException() { } - - public UnsupportedVersionException(string message) : base(message) { } - } -} diff --git a/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfig.cs b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfig.cs new file mode 100644 index 000000000..b15b46e3f --- /dev/null +++ b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfig.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace FunctionsNetHost.Grpc +{ + /// + /// Represents a worker configuration instance. + /// + public sealed class WorkerConfig + { + public WorkerDescription? Description { set; get; } + } +} diff --git a/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigSerializerContext.cs b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigSerializerContext.cs new file mode 100644 index 000000000..d37bcd11e --- /dev/null +++ b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigSerializerContext.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Text.Json.Serialization; + +namespace FunctionsNetHost.Grpc +{ + [JsonSerializable(typeof(WorkerConfig))] + [JsonSourceGenerationOptions(IncludeFields = true, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] + internal partial class WorkerConfigSerializerContext : JsonSerializerContext { } +} diff --git a/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigUtils.cs b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigUtils.cs new file mode 100644 index 000000000..740e335d5 --- /dev/null +++ b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigUtils.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Text.Json; + +namespace FunctionsNetHost.Grpc +{ + internal static class WorkerConfigUtils + { + /// + /// Build and returns an instance of from the worker.config.json file if present in the application directory. + /// + /// The directory where function app deployed payload is present. + internal static WorkerConfig? GetWorkerConfig(string applicationDirectory) + { + try + { + var workerConfigPath = Path.Combine(applicationDirectory, "worker.config.json"); + + if (!File.Exists(workerConfigPath)) + { + Logger.Log($"worker.config.json not found at {workerConfigPath}. This may indicate missing app payload."); + return null; + } + + var jsonString = File.ReadAllText(workerConfigPath); + return JsonSerializer.Deserialize(jsonString, WorkerConfigSerializerContext.Default.WorkerConfig); + } + catch (Exception ex) + { + Logger.Log($"Error in WorkerConfigUtils.GetWorkerConfig.{ex}"); + return null; + } + } + } +} diff --git a/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs new file mode 100644 index 000000000..9ba358818 --- /dev/null +++ b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace FunctionsNetHost.Grpc +{ + public sealed class WorkerDescription + { + public string? DefaultWorkerPath { set; get; } + + public bool IsSpecializable { set; get; } + } +} From 2901c7931a3565920f02c360afb5dcf3e9875897 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 10 Oct 2023 13:51:51 -0700 Subject: [PATCH 3/6] Fix application path. --- host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs index 58d25e103..e65fe4402 100644 --- a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs +++ b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs @@ -68,7 +68,7 @@ private async Task Process(StreamingMessage msg) break; } - var applicationExePath = workerConfig.Description.DefaultWorkerPath; + var applicationExePath = Path.Combine(envReloadRequest.FunctionAppDirectory, workerConfig.Description.DefaultWorkerPath!); Logger.LogTrace($"application path {applicationExePath}"); foreach (var kv in envReloadRequest.EnvironmentVariables) From 3e05c5ca3bd8a5a65d6768811650010145d53b77 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 10 Oct 2023 15:23:13 -0700 Subject: [PATCH 4/6] package version bump --- .../Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec b/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec index c2ab2b44b..36c3591a6 100644 --- a/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec +++ b/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec @@ -4,7 +4,7 @@ Microsoft.Azure.Functions.DotNetIsolatedNativeHost Microsoft Azure Functions dotnet-isolated native host dotnet-isolated azure-functions azure - 1.0.0 + 1.0.1 Microsoft Microsoft https://github.com/Azure/azure-functions-dotnet-worker From 0518ec6bd08de6c559ca3deaecfe03baf1302c41 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 10 Oct 2023 17:14:20 -0700 Subject: [PATCH 5/6] PR feedback: Switched to async overload for deserialization. Updated global.json to use rc2 --- .../EnvironmentReloadUnsupportedException.cs | 2 +- .../Grpc/IncomingGrpcMessageHandler.cs | 2 +- .../Grpc/WorkerConfig/WorkerConfigUtils.cs | 23 +++++++++++-------- host/src/FunctionsNetHost/global.json | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs b/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs index af0ad0547..fe3ef8182 100644 --- a/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs +++ b/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs @@ -6,7 +6,7 @@ namespace Microsoft.Azure.Functions.Worker /// /// The exception that is thrown when the current function app payload does not support environment reload. /// - public sealed class EnvironmentReloadUnsupportedException : Exception + public sealed class EnvironmentReloadUnsupportedException : NotSupportedException { public EnvironmentReloadUnsupportedException() { } diff --git a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs index e65fe4402..75c5e77ed 100644 --- a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs +++ b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs @@ -52,7 +52,7 @@ private async Task Process(StreamingMessage msg) var envReloadRequest = msg.FunctionEnvironmentReloadRequest; - var workerConfig = WorkerConfigUtils.GetWorkerConfig(envReloadRequest.FunctionAppDirectory); + var workerConfig = await WorkerConfigUtils.GetWorkerConfig(envReloadRequest.FunctionAppDirectory); if (workerConfig?.Description is null) { diff --git a/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigUtils.cs b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigUtils.cs index 740e335d5..98c430718 100644 --- a/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigUtils.cs +++ b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerConfigUtils.cs @@ -8,23 +8,26 @@ namespace FunctionsNetHost.Grpc internal static class WorkerConfigUtils { /// - /// Build and returns an instance of from the worker.config.json file if present in the application directory. + /// Builds and returns an instance of from the worker.config.json file if present in the application directory. /// /// The directory where function app deployed payload is present. - internal static WorkerConfig? GetWorkerConfig(string applicationDirectory) + internal static async Task GetWorkerConfig(string applicationDirectory) { + string workerConfigPath = string.Empty; + try { - var workerConfigPath = Path.Combine(applicationDirectory, "worker.config.json"); + workerConfigPath = Path.Combine(applicationDirectory, "worker.config.json"); - if (!File.Exists(workerConfigPath)) - { - Logger.Log($"worker.config.json not found at {workerConfigPath}. This may indicate missing app payload."); - return null; - } + using Stream stream = File.OpenRead(workerConfigPath); + var workerConfig = await JsonSerializer.DeserializeAsync(stream, WorkerConfigSerializerContext.Default.WorkerConfig); - var jsonString = File.ReadAllText(workerConfigPath); - return JsonSerializer.Deserialize(jsonString, WorkerConfigSerializerContext.Default.WorkerConfig); + return workerConfig; + } + catch (FileNotFoundException) + { + Logger.Log($"worker.config.json not found at {workerConfigPath}. This may indicate missing app payload."); + return null; } catch (Exception ex) { diff --git a/host/src/FunctionsNetHost/global.json b/host/src/FunctionsNetHost/global.json index f735d6ed6..27928313f 100644 --- a/host/src/FunctionsNetHost/global.json +++ b/host/src/FunctionsNetHost/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100-rc.1.23455.8", + "version": "8.0.100-rc.2.23502.2", "allowPrerelease": true, "rollForward": "latestMinor" } From 62fc978479df7626a7f278caa61936014e3a7816 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Wed, 11 Oct 2023 10:14:10 -0700 Subject: [PATCH 6/6] PR feedback - type renames as suggested. --- ...ception.cs => EnvironmentReloadNotSupportedException.cs} | 6 +++--- .../src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs | 4 ++-- .../FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename host/src/FunctionsNetHost/Grpc/Exceptions/{EnvironmentReloadUnsupportedException.cs => EnvironmentReloadNotSupportedException.cs} (60%) diff --git a/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs b/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadNotSupportedException.cs similarity index 60% rename from host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs rename to host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadNotSupportedException.cs index fe3ef8182..a0996236e 100644 --- a/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadUnsupportedException.cs +++ b/host/src/FunctionsNetHost/Grpc/Exceptions/EnvironmentReloadNotSupportedException.cs @@ -6,10 +6,10 @@ namespace Microsoft.Azure.Functions.Worker /// /// The exception that is thrown when the current function app payload does not support environment reload. /// - public sealed class EnvironmentReloadUnsupportedException : NotSupportedException + public sealed class EnvironmentReloadNotSupportedException : NotSupportedException { - public EnvironmentReloadUnsupportedException() { } + public EnvironmentReloadNotSupportedException() { } - public EnvironmentReloadUnsupportedException(string message) : base(message) { } + public EnvironmentReloadNotSupportedException(string message) : base(message) { } } } diff --git a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs index 75c5e77ed..af0a5c43f 100644 --- a/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs +++ b/host/src/FunctionsNetHost/Grpc/IncomingGrpcMessageHandler.cs @@ -61,10 +61,10 @@ private async Task Process(StreamingMessage msg) } // function app payload which uses an older version of Microsoft.Azure.Functions.Worker package does not support specialization. - if (!workerConfig.Description.IsSpecializable) + if (!workerConfig.Description.CanUsePlaceholder) { Logger.LogTrace("App payload uses an older version of worker package which does not support specialization."); - responseMessage.FunctionEnvironmentReloadResponse = BuildFailedEnvironmentReloadResponse(new EnvironmentReloadUnsupportedException()); + responseMessage.FunctionEnvironmentReloadResponse = BuildFailedEnvironmentReloadResponse(new EnvironmentReloadNotSupportedException()); break; } diff --git a/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs index 9ba358818..5ad21dd0a 100644 --- a/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs +++ b/host/src/FunctionsNetHost/Grpc/WorkerConfig/WorkerDescription.cs @@ -7,6 +7,6 @@ public sealed class WorkerDescription { public string? DefaultWorkerPath { set; get; } - public bool IsSpecializable { set; get; } + public bool CanUsePlaceholder { set; get; } } }