feat(lmxproxy): phase 1 — v2 protocol types and domain model

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-03-21 23:41:56 -04:00
parent 08d2a07d8b
commit 0d63fb1105
87 changed files with 3389 additions and 956 deletions

View File

@@ -1,87 +1,10 @@
using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Serilog;
using Topshelf;
using ZB.MOM.WW.LmxProxy.Host.Configuration;
namespace ZB.MOM.WW.LmxProxy.Host
{
internal class Program
internal static class Program
{
private static void Main(string[] args)
static void Main(string[] args)
{
// Build configuration
IConfigurationRoot? configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", true, true)
.AddEnvironmentVariables()
.Build();
// Configure Serilog from appsettings.json
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
try
{
Log.Information("Starting ZB.MOM.WW.LmxProxy.Host");
// Load configuration
var config = new LmxProxyConfiguration();
configuration.Bind(config);
// Validate configuration
if (!ConfigurationValidator.ValidateAndLog(config))
{
Log.Fatal("Configuration validation failed. Please check the configuration and try again.");
Environment.ExitCode = 1;
return;
}
// Configure and run the Windows service using TopShelf
TopshelfExitCode exitCode = HostFactory.Run(hostConfig =>
{
hostConfig.Service<LmxProxyService>(serviceConfig =>
{
serviceConfig.ConstructUsing(() => new LmxProxyService(config));
serviceConfig.WhenStarted(service => service.Start());
serviceConfig.WhenStopped(service => service.Stop());
serviceConfig.WhenPaused(service => service.Pause());
serviceConfig.WhenContinued(service => service.Continue());
serviceConfig.WhenShutdown(service => service.Shutdown());
});
hostConfig.UseSerilog(Log.Logger);
hostConfig.SetServiceName("ZB.MOM.WW.LmxProxy.Host");
hostConfig.SetDisplayName("SCADA Bridge LMX Proxy");
hostConfig.SetDescription("Provides gRPC access to Archestra MxAccess for SCADA Bridge");
hostConfig.StartAutomatically();
hostConfig.EnableServiceRecovery(recoveryConfig =>
{
recoveryConfig.RestartService(config.ServiceRecovery.FirstFailureDelayMinutes);
recoveryConfig.RestartService(config.ServiceRecovery.SecondFailureDelayMinutes);
recoveryConfig.RestartService(config.ServiceRecovery.SubsequentFailureDelayMinutes);
recoveryConfig.SetResetPeriod(config.ServiceRecovery.ResetPeriodDays);
});
hostConfig.OnException(ex => { Log.Fatal(ex, "Unhandled exception in service"); });
});
Log.Information("Service exited with code: {ExitCode}", exitCode);
Environment.ExitCode = (int)exitCode;
}
catch (Exception ex)
{
Log.Fatal(ex, "Failed to start service");
Environment.ExitCode = 1;
}
finally
{
Log.CloseAndFlush();
}
// Placeholder - Phase 3 will implement full Topshelf startup.
}
}
}