feat: add CLI debug snapshot command for one-shot instance state inspection

Adds `debug snapshot --id <int>` to query a running instance's current
attribute values and alarm states without the subscribe/stream overhead
of the debug view. Routes through ManagementActor → CommunicationService
→ site DeploymentManager → InstanceActor using the existing remote query
pattern.
This commit is contained in:
Joseph Doherty
2026-03-18 07:16:22 -04:00
parent 6ee820b0f0
commit 9c6e3c2e56
14 changed files with 144 additions and 4 deletions

View File

@@ -71,6 +71,7 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
// Debug View — route to Instance Actors
Receive<SubscribeDebugViewRequest>(RouteDebugViewSubscribe);
Receive<UnsubscribeDebugViewRequest>(RouteDebugViewUnsubscribe);
Receive<DebugSnapshotRequest>(RouteDebugSnapshot);
// Internal startup messages
Receive<StartupConfigsLoaded>(HandleStartupConfigsLoaded);
@@ -453,6 +454,22 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
}
}
private void RouteDebugSnapshot(DebugSnapshotRequest request)
{
if (_instanceActors.TryGetValue(request.InstanceUniqueName, out var instanceActor))
{
instanceActor.Forward(request);
}
else
{
_logger.LogWarning(
"Debug snapshot for unknown instance {Instance}", request.InstanceUniqueName);
Sender.Tell(new DebugViewSnapshot(
request.InstanceUniqueName, Array.Empty<Commons.Messages.Streaming.AttributeValueChanged>(),
Array.Empty<Commons.Messages.Streaming.AlarmStateChanged>(), DateTimeOffset.UtcNow));
}
}
/// <summary>
/// WP-33: Handles system-wide artifact deployment (shared scripts, external systems, etc.).
/// Persists artifacts to SiteStorageService and recompiles shared scripts.

View File

@@ -133,6 +133,9 @@ public class InstanceActor : ReceiveActor
Receive<SubscribeDebugViewRequest>(HandleSubscribeDebugView);
Receive<UnsubscribeDebugViewRequest>(HandleUnsubscribeDebugView);
// Debug snapshot (one-shot, no subscription)
Receive<DebugSnapshotRequest>(HandleDebugSnapshot);
// Handle internal messages
Receive<LoadOverridesResult>(HandleOverridesLoaded);
}
@@ -399,6 +402,35 @@ public class InstanceActor : ReceiveActor
_instanceUniqueName, request.CorrelationId);
}
/// <summary>
/// One-shot debug snapshot — returns current state without registering a subscriber.
/// </summary>
private void HandleDebugSnapshot(DebugSnapshotRequest request)
{
var attributeValues = _attributes.Select(kvp => new AttributeValueChanged(
_instanceUniqueName,
kvp.Key,
kvp.Key,
kvp.Value,
_attributeQualities.GetValueOrDefault(kvp.Key, "Good"),
DateTimeOffset.UtcNow)).ToList();
var alarmStates = _alarmStates.Select(kvp => new AlarmStateChanged(
_instanceUniqueName,
kvp.Key,
kvp.Value,
0,
DateTimeOffset.UtcNow)).ToList();
var snapshot = new DebugViewSnapshot(
_instanceUniqueName,
attributeValues,
alarmStates,
DateTimeOffset.UtcNow);
Sender.Tell(snapshot);
}
/// <summary>
/// Publishes attribute change to stream and notifies child Script/Alarm actors.
/// WP-22: Tell for attribute notifications (fire-and-forget, never blocks).