using System.Text.Json.Serialization; namespace Mbproxy.Admin; // ── Wire DTOs for GET /status.json ─────────────────────────────────────────── // Field names must match design.md "Status page" tables EXACTLY (camelCase via // JsonKnownNamingPolicy.CamelCase on the source-gen context). /// /// Top-level response envelope for GET /status.json. /// public sealed record StatusResponse( ServiceFields Service, ListenersAggregate Listeners, IReadOnlyList Plcs); /// Service-wide identity and reload counters. public sealed record ServiceFields( long UptimeSeconds, string Version, DateTimeOffset? ConfigLastReloadUtc, int ConfigReloadCount, int ConfigReloadRejectedCount); /// Aggregate listener state across all configured PLCs. public sealed record ListenersAggregate(int Bound, int Configured); /// Per-PLC status row. public sealed record PlcStatus( string Name, string Host, int ListenPort, PlcListenerStatus Listener, PlcClientsStatus Clients, PlcPdusStatus Pdus, PlcBackendStatus Backend, PlcBytesStatus Bytes); /// Listener state sub-object. public sealed record PlcListenerStatus( string State, string? LastBindError, int RecoveryAttempts); /// Connected-clients sub-object. public sealed record PlcClientsStatus( int Connected, IReadOnlyList RemoteEndpoints); /// Per-connection-pair snapshot for the status page. public sealed record ClientSnapshot( string Remote, DateTimeOffset ConnectedAtUtc, long PdusForwarded); /// PDU counters sub-object. public sealed record PlcPdusStatus( long Forwarded, FcCounts ByFc, long RewrittenSlots, long PartialBcdWarnings); /// Per-function-code request counts. public sealed record FcCounts( long Fc03, long Fc04, long Fc06, long Fc16, long Other); /// /// Backend connect, exception, and multiplexer telemetry. Phase 9 added /// InFlight, MaxInFlight, TxIdWraps, DisconnectCascades, and /// QueueDepth. Phase 10 added the three coalescing counters /// (CoalescedHitCount, CoalescedMissCount, CoalescedResponseToDeadUpstream); /// the dashboard-side derived coalescingRatio is intentionally NOT carried on the wire /// — consumers compute Hit / (Hit + Miss). Phase 11 added the five cache counters /// (CacheHitCount, CacheMissCount, CacheInvalidations, /// CacheEntryCount, CacheBytes); the dashboard-side derived /// cacheHitRatio is intentionally NOT carried on the wire. /// public sealed record PlcBackendStatus( long ConnectsSuccess, long ConnectsFailed, ExceptionCounts ExceptionsByCode, double LastRoundTripMs, long InFlight, long MaxInFlight, long TxIdWraps, long DisconnectCascades, long QueueDepth, long CoalescedHitCount, long CoalescedMissCount, long CoalescedResponseToDeadUpstream, long CacheHitCount, long CacheMissCount, long CacheInvalidations, long CacheEntryCount, long CacheBytes); /// Modbus exception counts by code. public sealed record ExceptionCounts( long Code01, long Code02, long Code03, long Code04); /// Byte-transfer counters. public sealed record PlcBytesStatus( long UpstreamIn, long UpstreamOut); // ── Source-generation context ───────────────────────────────────────────────── // TreatWarningsAsErrors is on, so the context must include every reachable type. [JsonSerializable(typeof(StatusResponse))] [JsonSourceGenerationOptions( WriteIndented = false, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] internal partial class StatusJsonContext : JsonSerializerContext;