145 lines
8.3 KiB
Markdown
145 lines
8.3 KiB
Markdown
# Component: Host
|
||
|
||
## Purpose
|
||
|
||
The Host component is the single deployable executable for the entire ScadaLink system. The same binary runs on every node — central and site alike. The node's role is determined entirely by configuration (`appsettings.json`), not by which binary is deployed. On central nodes the Host additionally bootstraps ASP.NET Core to serve the Central UI and Inbound API web endpoints.
|
||
|
||
## Location
|
||
|
||
All nodes (central and site).
|
||
|
||
## Responsibilities
|
||
|
||
- Serve as the single entry point (`Program.cs`) for the ScadaLink process.
|
||
- Read and validate node configuration at startup before any actor system is created.
|
||
- Register the correct set of component services and actors based on the configured node role.
|
||
- Bootstrap the Akka.NET actor system with Remoting, Clustering, Persistence, and split-brain resolution via Akka.Hosting.
|
||
- Host ASP.NET Core web endpoints on central nodes only.
|
||
- Configure structured logging (Serilog) with environment-specific enrichment.
|
||
- Support running as a Windows Service in production and as a console application during development.
|
||
- Perform graceful shutdown via Akka.NET CoordinatedShutdown when the service is stopped.
|
||
|
||
---
|
||
|
||
## Requirements
|
||
|
||
### REQ-HOST-1: Single Binary Deployment
|
||
|
||
The same compiled binary must be deployable to both central and site nodes. The node's role (Central or Site) is determined solely by configuration values in `appsettings.json` (or environment-specific overrides). There must be no separate build targets, projects, or conditional compilation symbols for central vs. site.
|
||
|
||
### REQ-HOST-2: Role-Based Service Registration
|
||
|
||
At startup the Host must inspect the configured node role and register only the component services appropriate for that role:
|
||
|
||
- **Shared** (both Central and Site): ClusterInfrastructure, Communication, HealthMonitoring, ExternalSystemGateway, NotificationService.
|
||
- **Central only**: TemplateEngine, DeploymentManager, Security, AuditLogging, CentralUI, InboundAPI.
|
||
- **Site only**: SiteRuntime, DataConnectionLayer, StoreAndForward, SiteEventLogging.
|
||
|
||
Components not applicable to the current role must not be registered in the DI container or the Akka.NET actor system.
|
||
|
||
### REQ-HOST-3: Configuration Binding
|
||
|
||
The Host must bind configuration sections from `appsettings.json` to strongly-typed options classes using the .NET Options pattern:
|
||
|
||
- `ScadaLink:Node` section bound to `NodeConfiguration` (Role, NodeHostname, SiteId, RemotingPort).
|
||
- `ScadaLink:Cluster` section bound to `ClusterConfiguration` (SeedNodes, SplitBrainResolverStrategy, StableAfter).
|
||
- `ScadaLink:Database` section bound to `DatabaseConfiguration` (Central: ConfigurationDb, MachineDataDb connection strings; Site: SQLite paths).
|
||
|
||
### REQ-HOST-4: Startup Validation
|
||
|
||
Before the Akka.NET actor system is created, the Host must validate all required configuration values and fail fast with a clear error message if any are missing or invalid. Validation rules include:
|
||
|
||
- `NodeConfiguration.Role` must be a valid `NodeRole` value.
|
||
- `NodeConfiguration.NodeHostname` must not be null or empty.
|
||
- `NodeConfiguration.RemotingPort` must be in valid port range (1–65535).
|
||
- Site nodes must have a non-empty `SiteId`.
|
||
- Central nodes must have non-empty `ConfigurationDb` and `MachineDataDb` connection strings.
|
||
- Site nodes must have non-empty SQLite path values.
|
||
- At least two seed nodes must be configured.
|
||
|
||
### REQ-HOST-5: Windows Service Hosting
|
||
|
||
The Host must support running as a Windows Service via `UseWindowsService()`. When launched outside of a Windows Service context (e.g., during development), it must run as a standard console application. No code changes or conditional compilation are required to switch between the two modes.
|
||
|
||
### REQ-HOST-6: Akka.NET Bootstrap
|
||
|
||
The Host must configure the Akka.NET actor system using Akka.Hosting with:
|
||
|
||
- **Remoting**: Configured with the node's hostname and port from `NodeConfiguration`.
|
||
- **Clustering**: Configured with seed nodes and the node's cluster role from configuration.
|
||
- **Persistence**: Configured with the appropriate journal and snapshot store (SQL for central, SQLite for site).
|
||
- **Split-Brain Resolver**: Configured with the strategy and stable-after duration from `ClusterConfiguration`.
|
||
- **Actor registration**: Each component's actors registered via its `AddXxxActors()` extension method, conditional on the node's role.
|
||
|
||
### REQ-HOST-7: ASP.NET Web Endpoints (Central Only)
|
||
|
||
On central nodes, the Host must use `WebApplication.CreateBuilder` to produce a full ASP.NET Core host with Kestrel, and must map web endpoints for:
|
||
|
||
- Central UI (via `MapCentralUI()` extension method).
|
||
- Inbound API (via `MapInboundAPI()` extension method).
|
||
|
||
On site nodes, the Host must use `Host.CreateDefaultBuilder` to produce a generic `IHost` — **not** a `WebApplication`. This ensures no Kestrel server is started, no HTTP port is opened, and no web endpoint or middleware pipeline is configured. Site nodes are headless and must never accept inbound HTTP connections.
|
||
|
||
### REQ-HOST-8: Structured Logging
|
||
|
||
The Host must configure Serilog as the logging provider with:
|
||
|
||
- Configuration-driven sink setup (console and file sinks at minimum).
|
||
- Automatic enrichment of every log entry with `SiteId`, `NodeHostname`, and `NodeRole` properties sourced from `NodeConfiguration`.
|
||
- Structured (machine-parseable) output format.
|
||
|
||
### REQ-HOST-9: Graceful Shutdown
|
||
|
||
When the Host process receives a stop signal (Windows Service stop, `Ctrl+C`, or SIGTERM), it must trigger Akka.NET CoordinatedShutdown to allow actors to drain in-flight work before the process exits. The Host must not call `Environment.Exit()` or forcibly terminate the actor system without coordinated shutdown.
|
||
|
||
### REQ-HOST-10: Extension Method Convention
|
||
|
||
Each component library must expose its services to the Host via a consistent set of extension methods:
|
||
|
||
- `IServiceCollection.AddXxx()` — registers the component's DI services.
|
||
- `AkkaConfigurationBuilder.AddXxxActors()` — registers the component's actors with the Akka.NET actor system (for components that have actors).
|
||
- `WebApplication.MapXxx()` — maps the component's web endpoints (only for CentralUI and InboundAPI).
|
||
|
||
The Host's `Program.cs` calls these extension methods; the component libraries own the registration logic. This keeps the Host thin and each component self-contained.
|
||
|
||
---
|
||
|
||
## Component Registration Matrix
|
||
|
||
| Component | Central | Site | DI (`AddXxx`) | Actors (`AddXxxActors`) | Endpoints (`MapXxx`) |
|
||
|---|---|---|---|---|---|
|
||
| ClusterInfrastructure | Yes | Yes | Yes | Yes | No |
|
||
| Communication | Yes | Yes | Yes | Yes | No |
|
||
| HealthMonitoring | Yes | Yes | Yes | Yes | No |
|
||
| ExternalSystemGateway | Yes | Yes | Yes | Yes | No |
|
||
| NotificationService | Yes | Yes | Yes | Yes | No |
|
||
| TemplateEngine | Yes | No | Yes | Yes | No |
|
||
| DeploymentManager | Yes | No | Yes | Yes | No |
|
||
| Security | Yes | No | Yes | Yes | No |
|
||
| CentralUI | Yes | No | Yes | No | Yes |
|
||
| InboundAPI | Yes | No | Yes | No | Yes |
|
||
| SiteRuntime | No | Yes | Yes | Yes | No |
|
||
| DataConnectionLayer | No | Yes | Yes | Yes | No |
|
||
| StoreAndForward | No | Yes | Yes | Yes | No |
|
||
| SiteEventLogging | No | Yes | Yes | Yes | No |
|
||
| ConfigurationDatabase | Yes | No | Yes | No | No |
|
||
|
||
---
|
||
|
||
## Dependencies
|
||
|
||
- **All 15 component libraries**: The Host references every component project to call their extension methods.
|
||
- **Akka.Hosting**: For `AddAkka()` and the hosting configuration builder.
|
||
- **Akka.Remote.Hosting, Akka.Cluster.Hosting, Akka.Persistence.Hosting**: For Akka subsystem configuration.
|
||
- **Serilog.AspNetCore**: For structured logging integration.
|
||
- **Microsoft.Extensions.Hosting.WindowsServices**: For Windows Service support.
|
||
- **ASP.NET Core** (central only): For web endpoint hosting.
|
||
|
||
## Interactions
|
||
|
||
- **All components**: The Host is the composition root — it wires every component into the DI container and actor system.
|
||
- **Configuration Database**: The Host registers the DbContext and wires repository implementations to their interfaces. In development, triggers auto-migration; in production, validates schema version.
|
||
- **ClusterInfrastructure**: The Host configures the underlying Akka.NET cluster that ClusterInfrastructure manages at runtime.
|
||
- **CentralUI / InboundAPI**: The Host maps their web endpoints into the ASP.NET Core pipeline on central nodes.
|
||
- **HealthMonitoring**: The Host's startup validation and logging configuration provide the foundation for health reporting.
|