# Component: ServiceHost ## Purpose The entry point and lifecycle manager for the LmxProxy Windows service. Handles Topshelf service hosting, Serilog logging setup, component initialization/teardown ordering, and Windows SCM service recovery configuration. ## Location - `src/ZB.MOM.WW.LmxProxy.Host/Program.cs` — entry point, Serilog setup, Topshelf configuration. - `src/ZB.MOM.WW.LmxProxy.Host/LmxProxyService.cs` — service lifecycle (Start, Stop, Pause, Continue, Shutdown). ## Responsibilities - Configure and launch the Topshelf Windows service. - Load and validate configuration from `appsettings.json`. - Initialize Serilog logging. - Orchestrate service startup: create all components in dependency order, connect to MxAccess, start servers. - Orchestrate service shutdown: stop servers, dispose all components in reverse order. - Configure Windows SCM service recovery policies. ## 1. Entry Point (Program.cs) 1. Builds configuration from `appsettings.json` + environment variables via `ConfigurationBuilder`. 2. Configures Serilog from the `Serilog` section of appsettings (console + file sinks). 3. Validates configuration using `ConfigurationValidator.ValidateAndLog()`. 4. Configures Topshelf `HostFactory`: - Service name: `ZB.MOM.WW.LmxProxy.Host` - Display name: `SCADA Bridge LMX Proxy` - Start automatically on boot. - Service recovery: first failure 1 min, second 5 min, subsequent 10 min, reset period 1 day. 5. Runs the Topshelf host (blocks until service stops). ## 2. Service Lifecycle (LmxProxyService) ### 2.1 Startup Sequence (Start) Components are created and started in dependency order: 1. Validate configuration. 2. Check/generate TLS certificates (if TLS enabled). 3. Create `PerformanceMetrics`. 4. Create `ApiKeyService` — loads API keys from file. 5. Create `MxAccessClient` via factory. 6. Subscribe to connection state changes. 7. Connect to MxAccess synchronously — times out at `ConnectionTimeoutSeconds` (default 30s). 8. Start `MonitorConnectionAsync` (if `AutoReconnect` enabled). 9. Create `SubscriptionManager`. 10. Create `SessionManager`. 11. Create `HealthCheckService` + `DetailedHealthCheckService`. 12. Create `StatusReportService` + `StatusWebServer`. 13. Create `ScadaGrpcService`. 14. Create `ApiKeyInterceptor`. 15. Configure gRPC `Server` with TLS or insecure credentials. 16. Start gRPC server on `0.0.0.0:{GrpcPort}`. 17. Start `StatusWebServer`. ### 2.2 Shutdown Sequence (Stop) Components are stopped and disposed in reverse order: 1. Cancel reconnect monitor — wait **5 seconds** for exit. 2. Graceful gRPC server shutdown — **10-second** timeout, then kill. 3. Stop StatusWebServer — **5-second** wait. 4. Dispose all components in reverse creation order. 5. Disconnect from MxAccess — **10-second** timeout. ### 2.3 Other Lifecycle Events - **Pause**: Supported by Topshelf but behavior is a no-op beyond logging. - **Continue**: Resume from pause, no-op beyond logging. - **Shutdown**: System shutdown signal, triggers the same shutdown sequence as Stop. ## 3. Service Recovery (Windows SCM) Configured via Topshelf's `EnableServiceRecovery`: | Failure | Action | Delay | |---------|--------|-------| | First | Restart service | 1 minute | | Second | Restart service | 5 minutes | | Subsequent | Restart service | 10 minutes | | Reset period | — | 1 day | All values are configurable via `ServiceRecoveryConfiguration`. ## 4. Service Identity | Property | Value | |----------|-------| | Service name | `ZB.MOM.WW.LmxProxy.Host` | | Display name | `SCADA Bridge LMX Proxy` | | Start mode | Automatic | | Platform | x86 (.NET Framework 4.8) | | Framework | Topshelf | ## Dependencies - **Topshelf** — Windows service framework. - **Serilog** — structured logging (console + file sinks). - **Microsoft.Extensions.Configuration** — configuration loading. - **Configuration** — validated configuration objects. - All other components are created and managed by LmxProxyService. ## Interactions - **Configuration** is loaded and validated first; all other components receive their settings from it. - **MxAccessClient** is connected synchronously during startup. If connection fails within the timeout, the service fails to start. - **GrpcServer** and **StatusWebServer** are started last, after all dependencies are ready.