Skip to content

Commit

Permalink
refactor(producer-snapshot): converted to console app
Browse files Browse the repository at this point in the history
  • Loading branch information
ArneD committed Jan 8, 2025
1 parent 68b0cf6 commit 00e6918
Show file tree
Hide file tree
Showing 6 changed files with 312 additions and 208 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
namespace BuildingRegistry.Producer.Snapshot.Oslo
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Be.Vlaanderen.Basisregisters.Projector.ConnectedProjections;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public sealed class SnapshotProducers : BackgroundService
{
private readonly IConnectedProjectionsManager _projectionsManager;
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly ILogger<SnapshotProducers> _logger;

public SnapshotProducers(
IConnectedProjectionsManager projectionsManager,
IHostApplicationLifetime hostApplicationLifetime,
ILoggerFactory loggerFactory)
{
_projectionsManager = projectionsManager;
_hostApplicationLifetime = hostApplicationLifetime;
_logger = loggerFactory.CreateLogger<SnapshotProducers>();
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
await _projectionsManager.Start(stoppingToken);
}
catch (Exception exception)
{
_logger.LogCritical(exception, $"An error occurred while starting the {nameof(SnapshotProducers)}.");
_hostApplicationLifetime.StopApplication();
throw;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ namespace BuildingRegistry.Producer.Snapshot.Oslo.Infrastructure.Modules
using Microsoft.Extensions.Logging;
using NodaTime;

public class ApiModule : Module
public class ProducerModule : Module
{
private readonly IConfiguration _configuration;
private readonly IServiceCollection _services;
private readonly ILoggerFactory _loggerFactory;

public ApiModule(
public ProducerModule(
IConfiguration configuration,
IServiceCollection services,
ILoggerFactory loggerFactory)
Expand Down
175 changes: 151 additions & 24 deletions src/BuildingRegistry.Producer.Snapshot.Oslo/Infrastructure/Program.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,166 @@
namespace BuildingRegistry.Producer.Snapshot.Oslo.Infrastructure
namespace BuildingRegistry.Producer.Snapshot.Oslo.Infrastructure
{
using Be.Vlaanderen.Basisregisters.Api;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Be.Vlaanderen.Basisregisters.Aws.DistributedMutex;
using Destructurama;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Modules;
using Serilog;
using Serilog.Debugging;
using Serilog.Extensions.Logging;

public sealed class Program
public class Program
{
private Program()
protected Program()
{ }

public static void Main(string[] args)
=> Run(new ProgramOptions
public static async Task Main(string[] args)
{
AppDomain.CurrentDomain.FirstChanceException += (_, eventArgs) =>
Log.Debug(
eventArgs.Exception,
"FirstChanceException event raised in {AppDomain}.",
AppDomain.CurrentDomain.FriendlyName);

AppDomain.CurrentDomain.UnhandledException += (_, eventArgs) =>
Log.Fatal((Exception)eventArgs.ExceptionObject, "Encountered a fatal exception, exiting program.");

Log.Information("Initializing BuildingRegistry.Producer.Snapshot.Oslo");

var host = new HostBuilder()
.ConfigureAppConfiguration((_, configurationBuilder) =>
{
Hosting =
{
HttpPort = 6016
},
Logging =
configurationBuilder
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
.AddJsonFile($"appsettings.{Environment.MachineName.ToLowerInvariant()}.json", optional: true, reloadOnChange: false)
.AddEnvironmentVariables()
.AddCommandLine(args);
})
.ConfigureLogging((hostContext, loggingBuilder) =>
{
SelfLog.Enable(Console.WriteLine);
Log.Logger = new LoggerConfiguration() //NOSONAR logging configuration is safe
.ReadFrom.Configuration(hostContext.Configuration)
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithThreadId()
.Enrich.WithEnvironmentUserName()
.Destructure.JsonNetTypes()
.CreateLogger();
loggingBuilder.ClearProviders();
loggingBuilder.AddSerilog(Log.Logger);
})
.ConfigureServices((hostContext, services) =>
{
var healthChecksBuilder = services.AddHealthChecks();
var connectionStrings = hostContext.Configuration
.GetSection("ConnectionStrings")
.GetChildren();

foreach (var connectionString in connectionStrings
.Where(x => !x.Value.Contains("host", StringComparison.OrdinalIgnoreCase)))
{
WriteTextToConsole = false,
WriteJsonToConsole = false
},
Runtime =
healthChecksBuilder.AddSqlServer(
connectionString.Value,
name: $"sqlserver-{connectionString.Key.ToLowerInvariant()}",
tags: new[] { "db", "sql", "sqlserver" });
}

foreach (var connectionString in connectionStrings
.Where(x => x.Value.Contains("host", StringComparison.OrdinalIgnoreCase)))
{
CommandLineArgs = args
},
MiddlewareHooks =
healthChecksBuilder.AddNpgSql(
connectionString.Value,
name: $"npgsql-{connectionString.Key.ToLowerInvariant()}",
tags: new[] { "db", "sql", "npgsql" });
}

healthChecksBuilder.AddDbContextCheck<ProducerContext>(
$"dbcontext-{nameof(ProducerContext).ToLowerInvariant()}",
tags: new[] { "db", "sql", "sqlserver" });

var origins = hostContext.Configuration
.GetSection("Cors")
.GetChildren()
.Select(c => c.Value)
.ToArray();

foreach (var origin in origins)
{
ConfigureDistributedLock = DistributedLockOptions.LoadFromConfiguration
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.WithOrigins(origin);
});
});
}
});
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>((hostContext, builder) =>
{
var services = new ServiceCollection();
var loggerFactory = new SerilogLoggerFactory(Log.Logger);

builder.RegisterModule(new ProducerModule(hostContext.Configuration, services, loggerFactory));

builder
.RegisterType<SnapshotProducers>()
.As<IHostedService>()
.SingleInstance();

builder.Populate(services);
})
.ConfigureWebHostDefaults(webHostBuilder =>
webHostBuilder
.UseStartup<Startup>()
.UseKestrel())
.UseConsoleLifetime()
.Build();

Log.Information("Starting BuildingRegistry.Producer.Snapshot.Oslo");

var logger = host.Services.GetRequiredService<ILogger<Program>>();
var configuration = host.Services.GetRequiredService<IConfiguration>();

try
{
await DistributedLock<Program>.RunAsync(
async () => { await host.RunAsync().ConfigureAwait(false); },
DistributedLockOptions.LoadFromConfiguration(configuration),
logger)
.ConfigureAwait(false);
}
catch (AggregateException aggregateException)
{
foreach (var innerException in aggregateException.InnerExceptions)
{
logger.LogCritical(innerException, "Encountered a fatal exception, exiting program.");
}
}
catch (Exception e)
{
logger.LogCritical(e, "Encountered a fatal exception, exiting program.");
Log.CloseAndFlush();

private static void Run(ProgramOptions options)
=> new WebHostBuilder()
.UseDefaultForApi<Startup>(options)
.RunWithLock<Program>();
// Allow some time for flushing before shutdown.
await Task.Delay(500, default);
throw;
}
finally
{
logger.LogInformation("Stopping...");
}
}
}
}
Loading

0 comments on commit 00e6918

Please sign in to comment.