Phase 6.1 Stream E.2 partial - ResilienceStatusPublisherHostedService #105

Merged
dohertj2 merged 1 commits from phase-6-1-resilience-status-publisher into v2 2026-04-19 14:37:54 -04:00
Owner

Closes the HostedService half of Phase 6.1 Stream E.2. Admin UI /hosts column refresh + SignalR push + red-badge visual (E.3) remain in the visual-compliance pass.

Summary

  • ResilienceStatusPublisherHostedService : BackgroundService. 5 s tick; samples DriverResilienceStatusTracker + upserts into DriverInstanceResilienceStatus. Best-effort (DB outage logs + retries next tick; never crashes).
  • PersistOnceAsync public for deterministic tests.
  • CurrentBulkheadDepth currently persisted as 0 pending a narrower follow-up that wires Polly bulkhead-depth observer into the tracker.

Test plan

  • 6 new tests: empty tick is no-op; new row upsert with counters; second tick updates in place; multi-host independence; footprint round-trip; tick counter advances.
  • Full solution dotnet test: 1225 passing (was 1219, +6).

🤖 Generated with Claude Code

Closes the HostedService half of Phase 6.1 Stream E.2. Admin UI /hosts column refresh + SignalR push + red-badge visual (E.3) remain in the visual-compliance pass. ## Summary - `ResilienceStatusPublisherHostedService : BackgroundService`. 5 s tick; samples `DriverResilienceStatusTracker` + upserts into `DriverInstanceResilienceStatus`. Best-effort (DB outage logs + retries next tick; never crashes). - `PersistOnceAsync` public for deterministic tests. - `CurrentBulkheadDepth` currently persisted as 0 pending a narrower follow-up that wires Polly bulkhead-depth observer into the tracker. ## Test plan - [x] 6 new tests: empty tick is no-op; new row upsert with counters; second tick updates in place; multi-host independence; footprint round-trip; tick counter advances. - [x] Full solution `dotnet test`: 1225 passing (was 1219, +6). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dohertj2 added 1 commit 2026-04-19 14:37:45 -04:00
Closes the HostedService half of Phase 6.1 Stream E.2 flagged as a follow-up
when the DriverResilienceStatusTracker shipped in PR #82. The Admin /hosts
column refresh + SignalR push + red-badge visual (Stream E.3) remain
deferred to the visual-compliance pass — this PR owns the persistence
story alone.

Server.Hosting:
- ResilienceStatusPublisherHostedService : BackgroundService. Samples the
  DriverResilienceStatusTracker every TickInterval (default 5 s) and upserts
  each (DriverInstanceId, HostName) counter pair into
  DriverInstanceResilienceStatus via EF. New rows on first sight; in-place
  updates on subsequent ticks.
- PersistOnceAsync extracted public so tests drive one tick directly —
  matches the ScheduledRecycleHostedService pattern for deterministic
  timing.
- Best-effort persistence: a DB outage logs a warning + continues; the next
  tick retries. Never crashes the app on sample failure. Cancellation
  propagates through cleanly.
- Tracks the bulkhead depth / recycle / footprint columns the entity was
  designed for. CurrentBulkheadDepth currently persisted as 0 — the tracker
  doesn't yet expose live bulkhead depth; a narrower follow-up wires the
  Polly bulkhead-depth observer into the tracker.

Tests (6 new in ResilienceStatusPublisherHostedServiceTests):
- Empty tracker → tick is a no-op, zero rows written.
- Single-host counters → upsert a new row with ConsecutiveFailures + breaker
  timestamp + sampled timestamp.
- Second tick updates the existing row in place (not a second insert).
- Multi-host pairs persist independently.
- Footprint counters (Baseline + Current) round-trip.
- TickCount advances on every PersistOnceAsync call.

Full solution dotnet test: 1225 passing (was 1219, +6). Pre-existing
Client.CLI Subscribe flake unchanged.

Production wiring (Program.cs) example:
  builder.Services.AddSingleton<DriverResilienceStatusTracker>();
  builder.Services.AddHostedService<ResilienceStatusPublisherHostedService>();
  // Tracker gets wired into CapabilityInvoker via OtOpcUaServer resolution
  // + the existing Phase 6.1 layer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit 98b69ff4f9 into v2 2026-04-19 14:37:54 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#105