diff --git a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter.AspNetCore/ServiceCollectionExtensions.cs b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter.AspNetCore/ServiceCollectionExtensions.cs index 0eee456a8..bf279c6f2 100644 --- a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter.AspNetCore/ServiceCollectionExtensions.cs +++ b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter.AspNetCore/ServiceCollectionExtensions.cs @@ -50,10 +50,13 @@ private static IServiceCollection AddDaprStarter(this IServiceCollection service services.TryAddSingleton(); action.Invoke(); - if (isDelay) return services.AddHostedService(); var serviceProvider = services.BuildServiceProvider(); var options = serviceProvider.GetRequiredService>(); + var daprEnvironmentProvider = serviceProvider.GetRequiredService(); + daprEnvironmentProvider.CompleteDaprEnvironment(options.CurrentValue.DaprHttpPort, options.CurrentValue.DaprGrpcPort); + + if (isDelay) return services.AddHostedService(); ArgumentNullException.ThrowIfNull(options.CurrentValue.AppPort); var daprProcess = serviceProvider.GetRequiredService(); @@ -61,6 +64,7 @@ private static IServiceCollection AddDaprStarter(this IServiceCollection service return services; } + private sealed class DaprService { diff --git a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter.AspNetCore/_Imports.cs b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter.AspNetCore/_Imports.cs index ecdf48c3d..fc7e9a731 100644 --- a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter.AspNetCore/_Imports.cs +++ b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter.AspNetCore/_Imports.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See LICENSE.txt in the project root for license information. global using Masa.BuildingBlocks.Development.DaprStarter; +global using Masa.Contrib.Development.DaprStarter; global using Masa.Contrib.Development.DaprStarter.AspNetCore; global using Microsoft.AspNetCore.Hosting.Server; global using Microsoft.AspNetCore.Hosting.Server.Features; diff --git a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprEnvironmentProvider.cs b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprEnvironmentProvider.cs new file mode 100644 index 000000000..bb1d11e7a --- /dev/null +++ b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprEnvironmentProvider.cs @@ -0,0 +1,57 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Contrib.Development.DaprStarter; + +public class DaprEnvironmentProvider : IDaprEnvironmentProvider +{ + private const string GRPC_PORT = "DAPR_GRPC_PORT"; + + private const string HTTP_PORT = "DAPR_HTTP_PORT"; + + public ushort? GetHttpPort() => GetEnvironmentVariable(HTTP_PORT); + + public ushort? GetGrpcPort() => GetEnvironmentVariable(GRPC_PORT); + + private static ushort? GetEnvironmentVariable(string environment) + { + if (ushort.TryParse(Environment.GetEnvironmentVariable(environment), out ushort port)) + return port; + + return null; + } + + public bool TrySetHttpPort(ushort? httpPort) + { + if (httpPort is > 0) + { + SetHttpPort(httpPort.Value); + return true; + } + return false; + } + + // ReSharper disable once InconsistentNaming + public bool TrySetGrpcPort(ushort? grpcPort) + { + if (grpcPort is > 0) + { + SetGrpcPort(grpcPort.Value); + return true; + } + return false; + } + + public void SetHttpPort(ushort httpPort) => Environment.SetEnvironmentVariable(HTTP_PORT, httpPort.ToString()); + + // ReSharper disable once InconsistentNaming + public void SetGrpcPort(ushort grpcPort) => Environment.SetEnvironmentVariable(GRPC_PORT, grpcPort.ToString()); + + // ReSharper disable once InconsistentNaming + public void CompleteDaprEnvironment(ushort? httpPort, ushort? grpcPort) + { + if (grpcPort is > 0) SetGrpcPort(grpcPort.Value); + + if (httpPort is > 0) SetHttpPort(httpPort.Value); + } +} diff --git a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprProcess.cs b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprProcess.cs index a3024f242..ba7aaa1c9 100644 --- a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprProcess.cs +++ b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprProcess.cs @@ -26,8 +26,9 @@ public DaprProcess( IDaprProvider daprProvider, IProcessProvider processProvider, IOptionsMonitor daprOptions, + IDaprEnvironmentProvider daprEnvironmentProvider, ILogger? logger = null, - IOptions? masaAppConfigureOptions = null) : base(masaAppConfigureOptions) + IOptions? masaAppConfigureOptions = null) : base(daprEnvironmentProvider, masaAppConfigureOptions) { _daprProvider = daprProvider; _processProvider = processProvider; @@ -40,7 +41,7 @@ public void Start() { lock (_lock) { - var options = ConvertTo(_daprOptions.CurrentValue); + var options = ConvertToDaprCoreOptions(_daprOptions.CurrentValue); StartCore(options); } @@ -80,17 +81,21 @@ private void StartCore(DaprCoreOptions options) public void CompleteDaprEnvironment(ushort? httpPort, ushort? grpcPort) { - if (grpcPort is > 0) - CompleteDaprGrpcPortEnvironment(grpcPort.Value); - - if (httpPort is > 0) - CompleteDaprHttpPortEnvironment(httpPort.Value); + var setHttpPortResult = DaprEnvironmentProvider.TrySetHttpPort(httpPort); + if (setHttpPortResult) + { + SuccessDaprOptions!.TrySetHttpPort(httpPort); + _logger?.LogInformation("Update Dapr environment variables, DaprHttpPort: {HttpPort}", httpPort); + } - if (httpPort is > 0 && grpcPort is > 0) + var setGrpcPortResult = DaprEnvironmentProvider.TrySetGrpcPort(grpcPort); + if (setGrpcPortResult) { - SuccessDaprOptions!.SetPort(httpPort.Value, grpcPort.Value); - CompleteDaprEnvironment(httpPort.Value, grpcPort.Value, () => _isFirst = false); + SuccessDaprOptions!.TrySetGrpcPort(grpcPort); + _logger?.LogInformation("Update Dapr environment variables, DAPR_GRPC_PORT: {grpcPort}", grpcPort); } + + if (setHttpPortResult && setGrpcPortResult) _isFirst = false; } public void CheckAndCompleteDaprEnvironment(string? data) @@ -99,27 +104,11 @@ public void CheckAndCompleteDaprEnvironment(string? data) return; var httpPort = GetHttpPort(data); - var grpcPort = GetGrpcPort(data); + var grpcPort = GetgRPCPort(data); CompleteDaprEnvironment(httpPort, grpcPort); } - /// - /// Improve the information of HttpPort and GrpcPort successfully configured. - /// When Port is specified or Dapr is closed for other reasons after startup, the HttpPort and GrpcPort are the same as the Port assigned at the first startup. - /// - private void CompleteDaprEnvironment(ushort httpPort, ushort grpcPort, Action action) - { - if (CompleteDaprHttpPortEnvironment(httpPort) && CompleteDaprGrpcPortEnvironment(grpcPort)) - { - action.Invoke(); - _logger?.LogInformation( - "Update Dapr environment variables, DaprHttpPort: {HttpPort}, DAPR_GRPC_PORT: {GrpcPort}", - httpPort, - grpcPort); - } - } - public void Stop() { lock (_lock) @@ -176,7 +165,7 @@ public void Refresh(DaprOptions options) _isFirst = true; SuccessDaprOptions = null; _logger?.LogDebug("Dapr configuration refresh, Dapr AppId is {AppId}, restarting dapr, please wait...", options.AppId); - StartCore(ConvertTo(options)); + StartCore(ConvertToDaprCoreOptions(options)); } } diff --git a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprProcessBase.cs b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprProcessBase.cs index 51f4f2926..9ed141c6d 100644 --- a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprProcessBase.cs +++ b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/DaprProcessBase.cs @@ -8,10 +8,12 @@ public abstract class DaprProcessBase { private readonly IOptions? _masaAppConfigureOptions; + protected IDaprEnvironmentProvider DaprEnvironmentProvider { get; } + /// /// Use after getting dapr AppId and global AppId fails /// - private static readonly string _defaultAppId = (Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly()).GetName().Name!.Replace( + private static readonly string DefaultAppId = (Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly()).GetName().Name!.Replace( ".", Constant.DEFAULT_APPID_DELIMITER); @@ -20,18 +22,19 @@ public abstract class DaprProcessBase internal DaprCoreOptions? SuccessDaprOptions; - protected DaprProcessBase(IOptions? masaAppConfigureOptions) + protected DaprProcessBase(IDaprEnvironmentProvider daprEnvironmentProvider, IOptions? masaAppConfigureOptions) { + DaprEnvironmentProvider = daprEnvironmentProvider; _masaAppConfigureOptions = masaAppConfigureOptions; } - internal DaprCoreOptions ConvertTo(DaprOptions options) + internal DaprCoreOptions ConvertToDaprCoreOptions(DaprOptions options) { var appId = options.AppId; if (appId.IsNullOrWhiteSpace()) appId = _masaAppConfigureOptions?.Value.AppId; if (appId.IsNullOrWhiteSpace()) - appId = _defaultAppId; + appId = DefaultAppId; if (options.IsIncompleteAppId()) appId = $"{appId}{options.AppIdDelimiter}{options.AppIdSuffix ?? NetworkUtils.GetPhysicalAddress()}"; DaprCoreOptions @@ -40,8 +43,8 @@ internal DaprCoreOptions ConvertTo(DaprOptions options) options.AppPort ?? throw new ArgumentNullException(nameof(options), $"{options.AppPort} must be greater than 0"), options.AppProtocol, options.EnableSsl, - options.DaprGrpcPort, - options.DaprHttpPort, + options.DaprGrpcPort ?? DaprEnvironmentProvider.GetGrpcPort(), + options.DaprHttpPort ?? DaprEnvironmentProvider.GetHttpPort(), options.EnableHeartBeat) { HeartBeatInterval = options.HeartBeatInterval, @@ -89,12 +92,6 @@ internal CommandLineBuilder CreateCommandLineBuilder(DaprCoreOptions options) return commandLineBuilder; } - protected static bool CompleteDaprGrpcPortEnvironment(ushort daprGrpcPort) - => EnvironmentUtils.TrySetEnvironmentVariable("DAPR_GRPC_PORT", daprGrpcPort.ToString()); - - protected static bool CompleteDaprHttpPortEnvironment(ushort httpPort) - => EnvironmentUtils.TrySetEnvironmentVariable("DAPR_HTTP_PORT", httpPort.ToString()); - protected static ushort GetHttpPort(string data) { ushort httpPort = 0; @@ -106,13 +103,13 @@ protected static ushort GetHttpPort(string data) return httpPort; } - protected static ushort GetGrpcPort(string data) + protected static ushort GetgRPCPort(string data) { ushort grpcPort = 0; - var grpcPortMatch = Regex.Matches(data, GRPC_PORT_PATTERN); - if (grpcPortMatch.Count > 0) + var gRPCPortMatch = Regex.Matches(data, GRPC_PORT_PATTERN); + if (gRPCPortMatch.Count > 0) { - grpcPort = ushort.Parse(grpcPortMatch[0].Groups[1].ToString()); + grpcPort = ushort.Parse(gRPCPortMatch[0].Groups[1].ToString()); } return grpcPort; } diff --git a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/IDaprEnvironmentProvider.cs b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/IDaprEnvironmentProvider.cs new file mode 100644 index 000000000..364559292 --- /dev/null +++ b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/IDaprEnvironmentProvider.cs @@ -0,0 +1,36 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Contrib.Development.DaprStarter; + +public interface IDaprEnvironmentProvider +{ + ushort? GetHttpPort(); + + ushort? GetGrpcPort(); + + /// + /// Set the HttpPort environment variable + /// When httpPort is greater than 0, return true + /// + /// + /// + bool TrySetHttpPort(ushort? httpPort); + + /// + /// Set the grpcPort environment variable + /// When grpcPort is greater than 0, return true + /// + /// + /// + // ReSharper disable once InconsistentNaming + bool TrySetGrpcPort(ushort? grpcPort); + + void SetHttpPort(ushort httpPort); + + // ReSharper disable once InconsistentNaming + void SetGrpcPort(ushort grpcPort); + + // ReSharper disable once InconsistentNaming + void CompleteDaprEnvironment(ushort? httpPort, ushort? grpcPort); +} diff --git a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/Internal/Options/DaprCoreOptions.cs b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/Internal/Options/DaprCoreOptions.cs index e9650b760..2f19d375c 100644 --- a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/Internal/Options/DaprCoreOptions.cs +++ b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/Internal/Options/DaprCoreOptions.cs @@ -32,6 +32,7 @@ internal class DaprCoreOptions /// /// The gRPC port for Dapr to listen on /// + // ReSharper disable once InconsistentNaming public ushort? DaprGrpcPort { get; private set; } /// @@ -114,12 +115,13 @@ internal class DaprCoreOptions /// public int? DaprMaxRequestSize { get; set; } + // ReSharper disable once InconsistentNaming public DaprCoreOptions( string appId, ushort appPort, Protocol? appProtocol, bool? enableSsl, - ushort? daprGrpcPort, + ushort? daprGRPCPort, ushort? daprHttpPort, bool enableHeartBeat) { @@ -127,14 +129,29 @@ public DaprCoreOptions( AppPort = appPort; AppProtocol = appProtocol; EnableSsl = enableSsl; - DaprGrpcPort = daprGrpcPort; + DaprGrpcPort = daprGRPCPort; DaprHttpPort = daprHttpPort; EnableHeartBeat = enableHeartBeat; } - public void SetPort(ushort httpPort, ushort rpcPort) + public bool TrySetHttpPort(ushort? httpPort) { - DaprHttpPort ??= httpPort; - DaprGrpcPort ??= rpcPort; + if (DaprHttpPort == null && httpPort is > 0) + { + DaprHttpPort = httpPort; + return true; + } + return false; + } + + // ReSharper disable once InconsistentNaming + public bool TrySetGrpcPort(ushort? grpcPort) + { + if (DaprGrpcPort == null && grpcPort is > 0) + { + DaprGrpcPort = grpcPort; + return true; + } + return false; } } diff --git a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/ServiceCollectionExtensions.cs b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/ServiceCollectionExtensions.cs index 7b56cac91..e8d721294 100644 --- a/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/ServiceCollectionExtensions.cs +++ b/src/Contrib/Development/Masa.Contrib.Development.DaprStarter/ServiceCollectionExtensions.cs @@ -36,6 +36,7 @@ private static IServiceCollection AddDaprStarter(this IServiceCollection service services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); + services.TryAddSingleton(); return services; } diff --git a/src/Contrib/Development/Tests/Masa.Contrib.Development.DaprStarter.Tests/DaprEnvironmentProviderTest.cs b/src/Contrib/Development/Tests/Masa.Contrib.Development.DaprStarter.Tests/DaprEnvironmentProviderTest.cs new file mode 100644 index 000000000..8befd7e64 --- /dev/null +++ b/src/Contrib/Development/Tests/Masa.Contrib.Development.DaprStarter.Tests/DaprEnvironmentProviderTest.cs @@ -0,0 +1,85 @@ +// Copyright (c) MASA Stack All rights reserved. +// Licensed under the MIT License. See LICENSE.txt in the project root for license information. + +namespace Masa.Contrib.Development.DaprStarter.Tests; + +[TestClass] +public class DaprEnvironmentProviderTest +{ + private const string GRPC_PORT = "DAPR_GRPC_PORT"; + + private const string HTTP_PORT = "DAPR_HTTP_PORT"; + private readonly DaprEnvironmentProvider _daprEnvironmentProvider; + + public DaprEnvironmentProviderTest() + { + _daprEnvironmentProvider = new DaprEnvironmentProvider(); + Environment.SetEnvironmentVariable(HTTP_PORT, null); + Environment.SetEnvironmentVariable(GRPC_PORT, null); + } + + [TestMethod] + public void TestTrySetHttpPort() + { + ushort? httpPort = null; + var result = _daprEnvironmentProvider.TrySetHttpPort(httpPort); + Assert.AreEqual(false, result); + + httpPort = _daprEnvironmentProvider.GetHttpPort(); + Assert.AreEqual(null, httpPort); + + httpPort = 10; + result = _daprEnvironmentProvider.TrySetHttpPort(httpPort); + Assert.AreEqual(true, result); + + var port = _daprEnvironmentProvider.GetHttpPort(); + Assert.AreEqual(httpPort, port); + } + + [TestMethod] + // ReSharper disable once InconsistentNaming + public void TestTrySetGrpcPort() + { + // ReSharper disable once InconsistentNaming + ushort? grpcPort = null; + var result = _daprEnvironmentProvider.TrySetGrpcPort(grpcPort); + Assert.AreEqual(false, result); + + grpcPort = _daprEnvironmentProvider.GetGrpcPort(); + Assert.AreEqual(null, grpcPort); + + grpcPort = 10; + result = _daprEnvironmentProvider.TrySetGrpcPort(grpcPort); + Assert.AreEqual(true, result); + + var port = _daprEnvironmentProvider.GetGrpcPort(); + Assert.AreEqual(grpcPort, port); + } + + [TestMethod] + // ReSharper disable once InconsistentNaming + public void TestCompleteDaprEnvironment() + { + // ReSharper disable once InconsistentNaming + ushort? grpcPort = null; + ushort? httpPort = null; + _daprEnvironmentProvider.CompleteDaprEnvironment(httpPort, grpcPort); + + grpcPort = _daprEnvironmentProvider.GetGrpcPort(); + Assert.AreEqual(null, grpcPort); + + httpPort = _daprEnvironmentProvider.GetHttpPort(); + Assert.AreEqual(null, httpPort); + + httpPort = 9; + grpcPort = 10; + + _daprEnvironmentProvider.CompleteDaprEnvironment(httpPort, grpcPort); + + httpPort = _daprEnvironmentProvider.GetHttpPort(); + Assert.AreEqual((ushort)9, httpPort); + + grpcPort = _daprEnvironmentProvider.GetGrpcPort(); + Assert.AreEqual((ushort)10, grpcPort); + } +} diff --git a/src/Contrib/Development/Tests/Masa.Contrib.Development.DaprStarter.Tests/Masa.Contrib.Development.DaprStarter.Tests.csproj b/src/Contrib/Development/Tests/Masa.Contrib.Development.DaprStarter.Tests/Masa.Contrib.Development.DaprStarter.Tests.csproj index a7d567ad5..209e4e854 100644 --- a/src/Contrib/Development/Tests/Masa.Contrib.Development.DaprStarter.Tests/Masa.Contrib.Development.DaprStarter.Tests.csproj +++ b/src/Contrib/Development/Tests/Masa.Contrib.Development.DaprStarter.Tests/Masa.Contrib.Development.DaprStarter.Tests.csproj @@ -8,11 +8,11 @@ - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -24,7 +24,7 @@ - +