using Grpc.Net.Client.Configuration; using Grpc.Net.ClientFactory; using MareSynchronosShared.Authentication; using MareSynchronosShared.Data; using MareSynchronosShared.Metrics; using MareSynchronosShared.Protos; using MareSynchronosShared.Services; using MareSynchronosShared.Utils; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using Prometheus; namespace MareSynchronosStaticFilesServer; public class Startup { private bool _isMain; public Startup(IConfiguration configuration) { Configuration = configuration; var mareSettings = Configuration.GetRequiredSection("MareSynchronos"); _isMain = string.IsNullOrEmpty(mareSettings.GetValue(nameof(StaticFilesServerConfiguration.RemoteCacheSourceUri), string.Empty)); } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddHttpContextAccessor(); services.AddLogging(); services.Configure(Configuration.GetRequiredSection("MareSynchronos")); services.Configure(Configuration.GetRequiredSection("MareSynchronos")); services.AddSingleton(Configuration); var mareConfig = Configuration.GetRequiredSection("MareSynchronos"); services.AddControllers(); services.AddSingleton(m => new MareMetrics(m.GetService>(), new List { MetricsAPI.CounterAuthenticationCacheHits, MetricsAPI.CounterAuthenticationFailures, MetricsAPI.CounterAuthenticationRequests, MetricsAPI.CounterAuthenticationSuccesses }, new List { MetricsAPI.GaugeFilesTotalSize, MetricsAPI.GaugeFilesTotal, MetricsAPI.GaugeFilesUniquePastDay, MetricsAPI.GaugeFilesUniquePastDaySize, MetricsAPI.GaugeFilesUniquePastHour, MetricsAPI.GaugeFilesUniquePastHourSize })); services.AddSingleton(); services.AddSingleton(); services.AddHostedService(m => m.GetService()); services.AddHostedService(); services.AddSingleton(); services.AddDbContextPool(options => { options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"), builder => { builder.MigrationsHistoryTable("_efmigrationshistory", "public"); }).UseSnakeCaseNamingConvention(); options.EnableThreadSafetyChecks(false); }, mareConfig.GetValue(nameof(MareConfigurationBase.DbContextPoolSize), 1024)); var noRetryConfig = new MethodConfig { Names = { MethodName.Default }, RetryPolicy = null }; services.AddGrpcClient("FileServer", c => { c.Address = new Uri(mareConfig.GetValue(nameof(StaticFilesServerConfiguration.FileServerGrpcAddress))); }).ConfigureChannel(c => { c.ServiceConfig = new ServiceConfig { MethodConfigs = { noRetryConfig } }; c.HttpHandler = new SocketsHttpHandler() { EnableMultipleHttp2Connections = true }; }); services.AddGrpcClient("MainServer", c => { c.Address = new Uri(mareConfig.GetValue(nameof(StaticFilesServerConfiguration.MainServerGrpcAddress))); }).ConfigureChannel(c => { c.ServiceConfig = new ServiceConfig { MethodConfigs = { noRetryConfig } }; c.HttpHandler = new SocketsHttpHandler() { EnableMultipleHttp2Connections = true }; }); services.AddAuthentication(options => { options.DefaultScheme = SecretKeyAuthenticationHandler.AuthScheme; }) .AddScheme(SecretKeyAuthenticationHandler.AuthScheme, options => { }); services.AddAuthorization(options => options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()); if (_isMain) { services.AddGrpc(o => { o.MaxReceiveMessageSize = null; }); services.AddSingleton, MareConfigurationServiceServer>(); } else { services.AddSingleton>(p => new MareConfigurationServiceClient( p.GetRequiredService>>(), p.GetRequiredService>(), p.GetRequiredService(), "FileServer")); services.AddHostedService(p => (MareConfigurationServiceClient)p.GetService>()); } services.AddSingleton>(p => new MareConfigurationServiceClient( p.GetRequiredService>>(), p.GetService>(), p.GetRequiredService(), "MainServer") ); services.AddHostedService(p => (MareConfigurationServiceClient)p.GetService>()); services.AddHealthChecks(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseHttpLogging(); app.UseRouting(); var config = app.ApplicationServices.GetRequiredService>(); var metricServer = new KestrelMetricServer(config.GetValueOrDefault(nameof(MareConfigurationBase.MetricsPort), 4981)); metricServer.Start(); app.UseHttpMetrics(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(e => { if (_isMain) { e.MapGrpcService(); } e.MapControllers(); e.MapHealthChecks("/health").WithMetadata(new AllowAnonymousAttribute()); }); } }