From 315946292da4fec450afd47afff1e994ce17a3a8 Mon Sep 17 00:00:00 2001 From: danielmarbach Date: Wed, 13 Mar 2024 17:44:29 +0100 Subject: [PATCH] Split extension methods and move to hostbuilder where possible to faciliate only starting what is required --- .../ServiceControlComponentRunner.cs | 3 +-- .../WebApplicationBuilderExtensions.cs | 5 +---- .../ServiceControlComponentRunner.cs | 7 ++----- .../WebApplicationBuilderExtensions.cs | 7 +------ ....cs => HostApplicationBuilderEtensions.cs} | 10 ++++------ .../Commands/ImportFailedAuditsCommand.cs | 6 ++---- .../Hosting/Commands/RunCommand.cs | 4 +++- ...cs => HostApplicationBuilderExtensions.cs} | 10 +++++----- .../ServiceControlComponentRunner.cs | 4 ++-- .../WebApplicationBuilderExtensions.cs | 5 +---- ...cs => HostApplicationBuilderExtensions.cs} | 17 ++--------------- .../Hosting/Commands/RunCommand.cs | 4 +++- .../HostApplicationBuilderExtensions.cs | 19 +++++++++++++++++++ .../RavenPersistedTypes.cs | 4 ++-- .../API/APIApprovals.cs | 2 +- .../EventHierarchy.cs | 5 +++-- ...cs => HostApplicationBuilderExtensions.cs} | 10 ++++------ .../Commands/ImportFailedErrorsCommand.cs | 6 ++---- .../Hosting/Commands/RunCommand.cs | 4 +++- ...cs => HostApplicationBuilderExtensions.cs} | 19 +++++++------------ 20 files changed, 68 insertions(+), 83 deletions(-) rename src/ServiceControl.Audit/{WebApplicationBuilderExtension.cs => HostApplicationBuilderEtensions.cs} (93%) rename src/ServiceControl.Audit/Infrastructure/WebApi/{WebApplicationBuilderExtensions.cs => HostApplicationBuilderExtensions.cs} (78%) rename src/ServiceControl.Monitoring/{WebApplicationBuilderExtensions.cs => HostApplicationBuilderExtensions.cs} (89%) create mode 100644 src/ServiceControl.Monitoring/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs rename src/ServiceControl/{WebApplicationBuilderExtension.cs => HostApplicationBuilderExtensions.cs} (93%) rename src/ServiceControl/Infrastructure/WebApi/{WebApiHostBuilderExtensions.cs => HostApplicationBuilderExtensions.cs} (75%) diff --git a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index 2c9a1d47b1..02feae5eb6 100644 --- a/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -11,7 +11,6 @@ using Infrastructure.DomainEvents; using Infrastructure.WebApi; using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -19,7 +18,6 @@ using NServiceBus; using NServiceBus.AcceptanceTesting; using NServiceBus.AcceptanceTesting.Support; - using NServiceBus.Configuration.AdvancedExtensibility; using Particular.ServiceControl; using Particular.ServiceControl.Hosting; using RavenDB.Shared; @@ -119,6 +117,7 @@ async Task InitializeServiceControl(ScenarioContext context) EnvironmentName = Environments.Development }); hostBuilder.AddServiceControl(settings, configuration, loggingSettings); + hostBuilder.AddServiceControlApi(); hostBuilder.AddServiceControlTesting(settings); diff --git a/src/ServiceControl.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs b/src/ServiceControl.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs index 5660b837a3..8455a2dd3b 100644 --- a/src/ServiceControl.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs +++ b/src/ServiceControl.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs @@ -23,11 +23,8 @@ public static void AddServiceControlTesting(this WebApplicationBuilder hostBuild // This facilitates receiving the test server anywhere where DI is available hostBuilder.Services.AddSingleton(provider => (TestServer)provider.GetRequiredService()); - // By default, ASP.NET Core uses the entry point assembly to discover controllers. When running - // inside a test runner the runner exe becomes the entry point which obviously has no controllers in it ;) - // so we are explicitly registering all necessary application parts. + // For acceptance testing purposes we are adding more controllers to the host var addControllers = hostBuilder.Services.AddControllers(); - addControllers.AddApplicationPart(typeof(Settings).Assembly); addControllers.AddApplicationPart(typeof(AcceptanceTest).Assembly); hostBuilder.Services.AddHttpClientDefaultsOverrides(settings); diff --git a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index afcb194f79..ea24da4cfc 100644 --- a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -9,21 +9,16 @@ namespace ServiceControl.Audit.AcceptanceTests.TestSupport using System.Threading; using System.Threading.Tasks; using AcceptanceTesting; - using Auditing; - using Infrastructure; using Infrastructure.Hosting; using Infrastructure.Hosting.Commands; using Infrastructure.Settings; using Infrastructure.WebApi; using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.TestHost; - using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using NServiceBus; using NServiceBus.AcceptanceTesting; using NServiceBus.AcceptanceTesting.Support; - using NServiceBus.Configuration.AdvancedExtensibility; public class ServiceControlComponentRunner( ITransportIntegration transportToUse, @@ -130,6 +125,8 @@ async Task InitializeServiceControl(ScenarioContext context) return criticalErrorContext.Stop(cancellationToken); }, settings, configuration, loggingSettings); + hostBuilder.AddServiceControlAuditApi(); + hostBuilder.AddServiceControlAuditTesting(settings); hostBuilderCustomization(hostBuilder); diff --git a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs index da69c2d069..8fb87a9f57 100644 --- a/src/ServiceControl.Audit.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs +++ b/src/ServiceControl.Audit.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs @@ -1,9 +1,7 @@ namespace ServiceControl.Audit.AcceptanceTests.TestSupport; using System; -using Auditing; using Infrastructure.Settings; -using Infrastructure.WebApi; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.TestHost; @@ -21,11 +19,8 @@ public static void AddServiceControlAuditTesting(this WebApplicationBuilder host // This facilitates receiving the test server anywhere where DI is available hostBuilder.Services.AddSingleton(provider => (TestServer)provider.GetRequiredService()); - // By default, ASP.NET Core uses the entry point assembly to discover controllers. When running - // inside a test runner the runner exe becomes the entry point which obviously has no controllers in it ;) - // so we are explicitly registering all necessary application parts. + // For acceptance testing purposes we are adding more controllers to the host var addControllers = hostBuilder.Services.AddControllers(); - addControllers.AddApplicationPart(typeof(Settings).Assembly); addControllers.AddApplicationPart(typeof(AcceptanceTest).Assembly); } } \ No newline at end of file diff --git a/src/ServiceControl.Audit/WebApplicationBuilderExtension.cs b/src/ServiceControl.Audit/HostApplicationBuilderEtensions.cs similarity index 93% rename from src/ServiceControl.Audit/WebApplicationBuilderExtension.cs rename to src/ServiceControl.Audit/HostApplicationBuilderEtensions.cs index c7009951e5..689c091493 100644 --- a/src/ServiceControl.Audit/WebApplicationBuilderExtension.cs +++ b/src/ServiceControl.Audit/HostApplicationBuilderEtensions.cs @@ -24,9 +24,9 @@ namespace ServiceControl.Audit; using Persistence; using Transports; -static class WebApplicationBuilderExtension +static class HostApplicationBuilderEtensions { - public static void AddServiceControlAudit(this WebApplicationBuilder builder, + public static void AddServiceControlAudit(this IHostApplicationBuilder builder, Func onCriticalError, Settings settings, EndpointConfiguration configuration, @@ -92,8 +92,6 @@ static class WebApplicationBuilderExtension services.AddHostedService(); } - builder.AddWebApi(settings.RootUrl); - builder.Services.AddWindowsService(); } @@ -110,7 +108,7 @@ static TransportSettings MapSettings(Settings settings) static void RecordStartup(Settings settings, LoggingSettings loggingSettings, EndpointConfiguration endpointConfiguration, IPersistenceConfiguration persistenceConfiguration) { - var version = FileVersionInfo.GetVersionInfo(typeof(WebApplicationBuilderExtension).Assembly.Location).ProductVersion; + var version = FileVersionInfo.GetVersionInfo(typeof(HostApplicationBuilderEtensions).Assembly.Location).ProductVersion; var startupMessage = $@" ------------------------------------------------------------- @@ -123,7 +121,7 @@ static void RecordStartup(Settings settings, LoggingSettings loggingSettings, En Persistence: {persistenceConfiguration.Name} -------------------------------------------------------------"; - var logger = LogManager.GetLogger(typeof(WebApplicationBuilderExtension)); + var logger = LogManager.GetLogger(typeof(HostApplicationBuilderEtensions)); logger.Info(startupMessage); endpointConfiguration.GetSettings().AddStartupDiagnosticsSection("Startup", new { diff --git a/src/ServiceControl.Audit/Infrastructure/Hosting/Commands/ImportFailedAuditsCommand.cs b/src/ServiceControl.Audit/Infrastructure/Hosting/Commands/ImportFailedAuditsCommand.cs index 6225f54480..c80ecf579f 100644 --- a/src/ServiceControl.Audit/Infrastructure/Hosting/Commands/ImportFailedAuditsCommand.cs +++ b/src/ServiceControl.Audit/Infrastructure/Hosting/Commands/ImportFailedAuditsCommand.cs @@ -4,8 +4,8 @@ using System.Threading; using System.Threading.Tasks; using Auditing; - using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Hosting; using NLog; using NServiceBus; using Settings; @@ -21,8 +21,7 @@ public override async Task Execute(HostArguments args, Settings settings) using var tokenSource = new CancellationTokenSource(); - // TODO: Ideally we would never want to actually bootstrap the web api. Figure out how - var hostBuilder = WebApplication.CreateBuilder(); + var hostBuilder = Host.CreateApplicationBuilder(); hostBuilder.AddServiceControlAudit((_, __) => { tokenSource.Cancel(); @@ -30,7 +29,6 @@ public override async Task Execute(HostArguments args, Settings settings) }, settings, endpointConfiguration, loggingSettings); using var app = hostBuilder.Build(); - app.UseServiceControlAudit(); await app.StartAsync(tokenSource.Token); var importer = app.Services.GetRequiredService(); diff --git a/src/ServiceControl.Audit/Infrastructure/Hosting/Commands/RunCommand.cs b/src/ServiceControl.Audit/Infrastructure/Hosting/Commands/RunCommand.cs index 373ed0d659..e7275213df 100644 --- a/src/ServiceControl.Audit/Infrastructure/Hosting/Commands/RunCommand.cs +++ b/src/ServiceControl.Audit/Infrastructure/Hosting/Commands/RunCommand.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Builder; using NServiceBus; using Settings; + using WebApi; class RunCommand : AbstractCommand { @@ -21,10 +22,11 @@ public override async Task Execute(HostArguments args, Settings settings) //Do nothing. The transports in NSB 8 are designed to handle broker outages. Audit ingestion will be paused when broker is unavailable. return Task.CompletedTask; }, settings, endpointConfiguration, loggingSettings); + hostBuilder.AddServiceControlAuditApi(); var app = hostBuilder.Build(); app.UseServiceControlAudit(); - await app.RunAsync(); + await app.RunAsync(settings.RootUrl); } } } \ No newline at end of file diff --git a/src/ServiceControl.Audit/Infrastructure/WebApi/WebApplicationBuilderExtensions.cs b/src/ServiceControl.Audit/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs similarity index 78% rename from src/ServiceControl.Audit/Infrastructure/WebApi/WebApplicationBuilderExtensions.cs rename to src/ServiceControl.Audit/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs index c29674b888..4eaa203c64 100644 --- a/src/ServiceControl.Audit/Infrastructure/WebApi/WebApplicationBuilderExtensions.cs +++ b/src/ServiceControl.Audit/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs @@ -1,15 +1,14 @@ namespace ServiceControl.Audit.Infrastructure.WebApi { + using System.Reflection; using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Hosting; - static class WebApplicationBuilderExtensions + static class HostApplicationBuilderExtensions { - public static void AddWebApi(this WebApplicationBuilder builder, string rootUrl) + public static void AddServiceControlAuditApi(this IHostApplicationBuilder builder) { - builder.WebHost.UseUrls(rootUrl); - builder.Services.AddCors(options => options.AddDefaultPolicy(Cors.GetDefaultPolicy())); // We're not explicitly adding Gzip here because it's already in the default list of supported compressors @@ -23,6 +22,7 @@ public static void AddWebApi(this WebApplicationBuilder builder, string rootUrl) options.ModelBinderProviders.Insert(0, new PagingInfoModelBindingProvider()); options.ModelBinderProviders.Insert(0, new SortInfoModelBindingProvider()); }); + controllers.AddApplicationPart(Assembly.GetExecutingAssembly()); controllers.AddJsonOptions(options => options.JsonSerializerOptions.CustomizeDefaults()); } } diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs index 1562db183b..f8b7e74c07 100644 --- a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs +++ b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/ServiceControlComponentRunner.cs @@ -8,8 +8,8 @@ namespace ServiceControl.Monitoring.AcceptanceTests.TestSupport using System.Threading.Tasks; using AcceptanceTesting; using Infrastructure; + using Infrastructure.WebApi; using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -17,7 +17,6 @@ namespace ServiceControl.Monitoring.AcceptanceTests.TestSupport using NServiceBus; using NServiceBus.AcceptanceTesting; using NServiceBus.AcceptanceTesting.Support; - using NServiceBus.Configuration.AdvancedExtensibility; using NServiceBus.Logging; class ServiceControlComponentRunner( @@ -107,6 +106,7 @@ async Task InitializeServiceControl(ScenarioContext context) context.Logs.Enqueue(logitem); return criticalErrorContext.Stop(cancellationToken); }, settings, configuration); + hostBuilder.AddServiceControlMonitoringApi(); hostBuilder.AddServiceControlMonitoringTesting(settings); diff --git a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs index 925156a0bb..22e2108d72 100644 --- a/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs +++ b/src/ServiceControl.Monitoring.AcceptanceTests/TestSupport/WebApplicationBuilderExtensions.cs @@ -18,11 +18,8 @@ public static void AddServiceControlMonitoringTesting(this WebApplicationBuilder hostBuilder.Services.AddKeyedSingleton(settings.EndpointName, (provider, _) => (TestServer)provider.GetRequiredService()); - // By default, ASP.NET Core uses the entry point assembly to discover controllers. When running - // inside a test runner the runner exe becomes the entry point which obviously has no controllers in it ;) - // so we are explicitly registering all necessary application parts. + // // For acceptance testing purposes we are adding more controllers to the host var addControllers = hostBuilder.Services.AddControllers(); - addControllers.AddApplicationPart(typeof(Settings).Assembly); addControllers.AddApplicationPart(typeof(AcceptanceTest).Assembly); } } \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/WebApplicationBuilderExtensions.cs b/src/ServiceControl.Monitoring/HostApplicationBuilderExtensions.cs similarity index 89% rename from src/ServiceControl.Monitoring/WebApplicationBuilderExtensions.cs rename to src/ServiceControl.Monitoring/HostApplicationBuilderExtensions.cs index cd8527da81..f263eb8363 100644 --- a/src/ServiceControl.Monitoring/WebApplicationBuilderExtensions.cs +++ b/src/ServiceControl.Monitoring/HostApplicationBuilderExtensions.cs @@ -6,11 +6,8 @@ namespace ServiceControl.Monitoring; using System.Threading.Tasks; using Infrastructure; using Infrastructure.Extensions; -using Infrastructure.WebApi; using Licensing; using Messaging; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpLogging; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -24,9 +21,9 @@ namespace ServiceControl.Monitoring; using Timings; using Transports; -public static class WebApplicationBuilderExtensions +public static class HostApplicationBuilderExtensions { - public static void AddServiceControlMonitoring(this WebApplicationBuilder hostBuilder, + public static void AddServiceControlMonitoring(this IHostApplicationBuilder hostBuilder, Func onCriticalError, Settings settings, EndpointConfiguration endpointConfiguration) { @@ -69,16 +66,6 @@ public static class WebApplicationBuilderExtensions ConfigureEndpoint(endpointConfiguration, onCriticalError, transportCustomization, settings); hostBuilder.UseNServiceBus(endpointConfiguration); - - // TODO Verify if that we need to check the expose API flag - // We also don't do this in the primary instance - hostBuilder.WebHost.UseUrls(settings.RootUrl); - var controllers = hostBuilder.Services.AddControllers(options => - { - options.Filters.Add(); - options.Filters.Add(); - }); - controllers.AddJsonOptions(options => options.JsonSerializerOptions.CustomizeDefaults()); } internal static void ConfigureEndpoint(EndpointConfiguration config, Func onCriticalError, ITransportCustomization transportCustomization, Settings settings) diff --git a/src/ServiceControl.Monitoring/Hosting/Commands/RunCommand.cs b/src/ServiceControl.Monitoring/Hosting/Commands/RunCommand.cs index ec4c96684e..9900f0eaaa 100644 --- a/src/ServiceControl.Monitoring/Hosting/Commands/RunCommand.cs +++ b/src/ServiceControl.Monitoring/Hosting/Commands/RunCommand.cs @@ -2,6 +2,7 @@ namespace ServiceControl.Monitoring { using System.Threading.Tasks; using Infrastructure; + using Infrastructure.WebApi; using Microsoft.AspNetCore.Builder; using NServiceBus; @@ -13,10 +14,11 @@ public override async Task Execute(Settings settings) var hostBuilder = WebApplication.CreateBuilder(); hostBuilder.AddServiceControlMonitoring((_, __) => Task.CompletedTask, settings, endpointConfiguration); + hostBuilder.AddServiceControlMonitoringApi(); var app = hostBuilder.Build(); app.UseServiceControlMonitoring(); - await app.RunAsync(); + await app.RunAsync(settings.RootUrl); } } } \ No newline at end of file diff --git a/src/ServiceControl.Monitoring/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs b/src/ServiceControl.Monitoring/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs new file mode 100644 index 0000000000..d0dd094ce9 --- /dev/null +++ b/src/ServiceControl.Monitoring/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs @@ -0,0 +1,19 @@ +namespace ServiceControl.Monitoring.Infrastructure.WebApi; + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Infrastructure; + +public static class HostApplicationBuilderExtensions +{ + public static void AddServiceControlMonitoringApi(this IHostApplicationBuilder hostBuilder) + { + var controllers = hostBuilder.Services.AddControllers(options => + { + options.Filters.Add(); + options.Filters.Add(); + }); + controllers.AddApplicationPart(typeof(Settings).Assembly); + controllers.AddJsonOptions(options => options.JsonSerializerOptions.CustomizeDefaults()); + } +} \ No newline at end of file diff --git a/src/ServiceControl.Persistence.Tests.RavenDB/RavenPersistedTypes.cs b/src/ServiceControl.Persistence.Tests.RavenDB/RavenPersistedTypes.cs index 873d9e288d..6329f03739 100644 --- a/src/ServiceControl.Persistence.Tests.RavenDB/RavenPersistedTypes.cs +++ b/src/ServiceControl.Persistence.Tests.RavenDB/RavenPersistedTypes.cs @@ -4,8 +4,8 @@ using System.Linq; using NUnit.Framework; using Particular.Approvals; - using Particular.ServiceControl; using Raven.Client.Documents.Indexes; + using ServiceBus.Management.Infrastructure.Settings; using ServiceControl.Persistence; class RavenPersistedTypes @@ -13,7 +13,7 @@ class RavenPersistedTypes [Test] public void Verify() { - var allTypes = typeof(WebApplicationBuilderExtension).Assembly.GetTypes().Concat(typeof(RavenQueryExtensions).Assembly.GetTypes()).Concat(typeof(EndpointsView).Assembly.GetTypes()); + var allTypes = typeof(Settings).Assembly.GetTypes().Concat(typeof(RavenQueryExtensions).Assembly.GetTypes()).Concat(typeof(EndpointsView).Assembly.GetTypes()); var documentTypes = allTypes .Where(type => typeof(AbstractIndexCreationTask).IsAssignableFrom(type)) diff --git a/src/ServiceControl.UnitTests/API/APIApprovals.cs b/src/ServiceControl.UnitTests/API/APIApprovals.cs index 610cd97e02..c4b20c7467 100644 --- a/src/ServiceControl.UnitTests/API/APIApprovals.cs +++ b/src/ServiceControl.UnitTests/API/APIApprovals.cs @@ -178,7 +178,7 @@ static IEnumerable GetCustomChecks() { var settings = (object)new Settings(); - var serviceControlTypes = typeof(WebApplicationBuilderExtension).Assembly + var serviceControlTypes = typeof(Settings).Assembly .GetTypes() .Where(t => t.IsAbstract == false); diff --git a/src/ServiceControl.UnitTests/EventHierarchy.cs b/src/ServiceControl.UnitTests/EventHierarchy.cs index e44a211a9f..f50526539e 100644 --- a/src/ServiceControl.UnitTests/EventHierarchy.cs +++ b/src/ServiceControl.UnitTests/EventHierarchy.cs @@ -3,7 +3,7 @@ using System.Linq; using NServiceBus; using NUnit.Framework; - using Particular.ServiceControl; + using ServiceBus.Management.Infrastructure.Settings; [TestFixture] class EventHierarchy @@ -11,13 +11,14 @@ class EventHierarchy [TestCase] public void EnsureEventHierarchyIsFlat() { - var serviceControlAssembly = typeof(WebApplicationBuilderExtension).Assembly; + var serviceControlAssembly = typeof(Settings).Assembly; var eventTypes = serviceControlAssembly.GetTypes().Where(typeof(IEvent).IsAssignableFrom).Where(x => !x.IsAbstract).ToArray(); var flatEvents = eventTypes.Where(t => t.BaseType == typeof(object)).ToArray(); var nonFlatEvents = eventTypes.Except(flatEvents).ToArray(); + Assert.IsNotEmpty(eventTypes); Assert.IsEmpty(nonFlatEvents, "Complex Event Hierarchy causes duplicate event handling with Azure ServiceBus and SubscribeToOwnEvents"); } } diff --git a/src/ServiceControl/WebApplicationBuilderExtension.cs b/src/ServiceControl/HostApplicationBuilderExtensions.cs similarity index 93% rename from src/ServiceControl/WebApplicationBuilderExtension.cs rename to src/ServiceControl/HostApplicationBuilderExtensions.cs index c02e3b7756..36745c09c1 100644 --- a/src/ServiceControl/WebApplicationBuilderExtension.cs +++ b/src/ServiceControl/HostApplicationBuilderExtensions.cs @@ -32,9 +32,9 @@ namespace Particular.ServiceControl using ServiceBus.Management.Infrastructure.Installers; using ServiceBus.Management.Infrastructure.Settings; - static class WebApplicationBuilderExtension + static class HostApplicationBuilderExtensions { - public static void AddServiceControl(this WebApplicationBuilder hostBuilder, Settings settings, EndpointConfiguration configuration, LoggingSettings loggingSettings) + public static void AddServiceControl(this IHostApplicationBuilder hostBuilder, Settings settings, EndpointConfiguration configuration, LoggingSettings loggingSettings) { ArgumentNullException.ThrowIfNull(configuration); @@ -101,8 +101,6 @@ public static void AddServiceControl(this WebApplicationBuilder hostBuilder, Set hostBuilder.AddExternalIntegrationEvents(); } - hostBuilder.AddWebApi([Assembly.GetExecutingAssembly()], settings.RootUrl); - hostBuilder.AddServicePulseSignalRNotifier(); hostBuilder.AddEmailNotifications(); hostBuilder.AddAsyncTimer(); @@ -141,7 +139,7 @@ static TransportSettings MapSettings(Settings settings) static void RecordStartup(Settings settings, LoggingSettings loggingSettings, EndpointConfiguration endpointConfiguration) { - var version = FileVersionInfo.GetVersionInfo(typeof(WebApplicationBuilderExtension).Assembly.Location).ProductVersion; + var version = FileVersionInfo.GetVersionInfo(typeof(HostApplicationBuilderExtensions).Assembly.Location).ProductVersion; var startupMessage = $@" ------------------------------------------------------------- @@ -154,7 +152,7 @@ static void RecordStartup(Settings settings, LoggingSettings loggingSettings, En Selected Transport Customization: {settings.TransportType} -------------------------------------------------------------"; - var logger = LogManager.GetLogger(typeof(WebApplicationBuilderExtension)); + var logger = LogManager.GetLogger(typeof(HostApplicationBuilderExtensions)); logger.Info(startupMessage); endpointConfiguration.GetSettings().AddStartupDiagnosticsSection("Startup", new { diff --git a/src/ServiceControl/Hosting/Commands/ImportFailedErrorsCommand.cs b/src/ServiceControl/Hosting/Commands/ImportFailedErrorsCommand.cs index 4bf8e9e973..e27df6b8a5 100644 --- a/src/ServiceControl/Hosting/Commands/ImportFailedErrorsCommand.cs +++ b/src/ServiceControl/Hosting/Commands/ImportFailedErrorsCommand.cs @@ -3,8 +3,8 @@ using System; using System.Threading; using System.Threading.Tasks; - using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Hosting; using NLog; using NServiceBus; using Operations; @@ -24,12 +24,10 @@ public override async Task Execute(HostArguments args, Settings settings) var loggingSettings = new LoggingSettings(settings.ServiceName, LogLevel.Info); - // TODO: Ideally we would never want to actually bootstrap the web api. Figure out how - var hostBuilder = WebApplication.CreateBuilder(); + var hostBuilder = Host.CreateApplicationBuilder(); hostBuilder.AddServiceControl(settings, endpointConfiguration, loggingSettings); using var app = hostBuilder.Build(); - app.UseServiceControl(); await app.StartAsync(); var importFailedErrors = app.Services.GetRequiredService(); diff --git a/src/ServiceControl/Hosting/Commands/RunCommand.cs b/src/ServiceControl/Hosting/Commands/RunCommand.cs index 509a17a989..570c67383c 100644 --- a/src/ServiceControl/Hosting/Commands/RunCommand.cs +++ b/src/ServiceControl/Hosting/Commands/RunCommand.cs @@ -1,6 +1,7 @@ namespace ServiceControl.Hosting.Commands { using System.Threading.Tasks; + using Infrastructure.WebApi; using Microsoft.AspNetCore.Builder; using NServiceBus; using Particular.ServiceControl; @@ -22,10 +23,11 @@ public override async Task Execute(HostArguments args, Settings settings) var hostBuilder = WebApplication.CreateBuilder(); hostBuilder.AddServiceControl(settings, endpointConfiguration, loggingSettings); + hostBuilder.AddServiceControlApi(); var app = hostBuilder.Build(); app.UseServiceControl(); - await app.RunAsync(); + await app.RunAsync(settings.RootUrl); } } } diff --git a/src/ServiceControl/Infrastructure/WebApi/WebApiHostBuilderExtensions.cs b/src/ServiceControl/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs similarity index 75% rename from src/ServiceControl/Infrastructure/WebApi/WebApiHostBuilderExtensions.cs rename to src/ServiceControl/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs index e18ea6d4d0..75e3c22bf7 100644 --- a/src/ServiceControl/Infrastructure/WebApi/WebApiHostBuilderExtensions.cs +++ b/src/ServiceControl/Infrastructure/WebApi/HostApplicationBuilderExtensions.cs @@ -1,26 +1,20 @@ namespace ServiceControl.Infrastructure.WebApi { - using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; + using Microsoft.Extensions.Hosting; using ServiceControl.CompositeViews.Messages; - static class WebApiHostBuilderExtensions + static class HostApplicationBuilderExtensions { - public static void AddWebApi(this WebApplicationBuilder builder, List apiAssemblies, string rootUrl) + public static void AddServiceControlApi(this IHostApplicationBuilder builder) { - builder.WebHost.UseUrls(rootUrl); - - foreach (var apiAssembly in apiAssemblies) - { - // This registers concrete classes that implement IApi. Currently it is hard to find out to what - // component those APIs should belong to so we leave it here for now. - builder.Services.RegisterApiTypes(apiAssembly); - } + // This registers concrete classes that implement IApi. Currently it is hard to find out to what + // component those APIs should belong to so we leave it here for now. + builder.Services.RegisterApiTypes(Assembly.GetExecutingAssembly()); builder.Services.AddCors(options => options.AddDefaultPolicy(Cors.GetDefaultPolicy())); @@ -35,6 +29,7 @@ public static void AddWebApi(this WebApplicationBuilder builder, List options.ModelBinderProviders.Insert(0, new PagingInfoModelBindingProvider()); options.ModelBinderProviders.Insert(0, new SortInfoModelBindingProvider()); }); + controllers.AddApplicationPart(Assembly.GetExecutingAssembly()); controllers.AddJsonOptions(options => options.JsonSerializerOptions.CustomizeDefaults()); var signalR = builder.Services.AddSignalR();