Phase 0 WP-0.10–0.12: Host skeleton, options classes, sample configs, and execution framework

- WP-0.10: Role-based Host startup (Central=WebApplication, Site=generic Host),
  15 component AddXxx() extension methods, MapCentralUI/MapInboundAPI stubs
- WP-0.11: 12 per-component options classes with config binding
- WP-0.12: Sample appsettings for central and site topologies
- Add execution procedure and checklist template to generate_plans.md
- Add phase-0-checklist.md for execution tracking
- Resolve all 21 open questions from plan generation
- Update IDataConnection with batch ops and IAsyncDisposable
57 tests pass, zero warnings.
This commit is contained in:
Joseph Doherty
2026-03-16 18:59:07 -04:00
parent 22e1eba58a
commit 8c2091dc0a
72 changed files with 1289 additions and 194 deletions

View File

@@ -22,13 +22,16 @@ Site clusters only. Central does not interact with machines directly.
Both OPC UA and LmxProxy implement the same interface:
```
IDataConnection
IDataConnection : IAsyncDisposable
├── Connect(connectionDetails) → void
├── Disconnect() → void
├── Subscribe(tagPath, callback) → subscriptionId
├── Unsubscribe(subscriptionId) → void
├── Read(tagPath) → value
├── ReadBatch(tagPaths) → values
├── Write(tagPath, value) → void
├── WriteBatch(values) → void
├── WriteBatchAndWait(values, flagPath, flagValue, responsePath, responseValue, timeout) → bool
└── Status → ConnectionHealth
```
@@ -43,7 +46,10 @@ Additional protocols can be added by implementing this interface.
| `Subscribe(tagPath, callback)` | OPC UA Monitored Items | `SubscribeAsync(addresses, onUpdate)` → server-streaming gRPC (`IAsyncEnumerable<VtqMessage>`) |
| `Unsubscribe(id)` | Remove Monitored Item | `ISubscription.DisposeAsync()` (cancels streaming RPC) |
| `Read(tagPath)` | OPC UA Read | `ReadAsync(address)``Vtq` |
| `ReadBatch(tagPaths)` | OPC UA Read (multiple nodes) | `ReadBatchAsync(addresses)``IDictionary<string, Vtq>` |
| `Write(tagPath, value)` | OPC UA Write | `WriteAsync(address, value)` |
| `WriteBatch(values)` | OPC UA Write (multiple nodes) | `WriteBatchAsync(values)` |
| `WriteBatchAndWait(...)` | OPC UA Write + poll for confirmation | `WriteBatchAndWaitAsync(values, flagAddress, flagValue, responseAddress, responseValue, timeout)` |
| `Status` | OPC UA session state | `IsConnected` property + keep-alive heartbeat (30-second interval via `GetConnectionStateAsync`) |
### Common Value Type
@@ -84,9 +90,6 @@ LmxProxy is a gRPC-based protocol for communicating with LMX data servers. An ex
- Subscription disposed via `ISubscription.DisposeAsync()`.
**Additional Capabilities (beyond IDataConnection)**:
- `ReadBatchAsync(addresses)` — bulk read in a single gRPC call.
- `WriteBatchAsync(values)` — bulk write in a single gRPC call.
- `WriteBatchAndWaitAsync(values, flagAddress, flagValue, responseAddress, responseValue, timeout)` — write-and-poll pattern for handshake protocols (default timeout: 30s, poll interval: 100ms).
- Built-in retry policy via Polly: exponential backoff (base delay × 2^attempt), configurable max attempts (default: 3), applied to reads. Transient errors: `Unavailable`, `DeadlineExceeded`, `ResourceExhausted`, `Aborted`.
- Operation metrics: count, errors, p95/p99 latency (ring buffer of last 1000 samples per operation).
- Correlation ID propagation for distributed tracing (configurable header name).