feat(alerts): AdminUI alarm ack/shelve via AdminOperationsActor singleton
T21: add an AdminUI path for acknowledging/shelving alarms that routes through the admin-pinned AdminOperationsActor cluster singleton, which republishes onto the same 'alarm-commands' DPS topic the OPC UA method path (T18) and the engine subscriber (T19) use. The broadcast + the ScriptedAlarmHostActor ownership filter handle cross-node routing, so the singleton needs no knowledge of which node owns the alarm. - Commons: AcknowledgeAlarmCommand/ShelveAlarmCommand (+ result records) and a shared AlarmCommandsTopic const; ScriptedAlarmHostActor now re-exports that const (mirrors the DriverControlTopic pattern). - AdminOperationsActor: two handlers map the control-plane messages to AlarmCommand (Acknowledge / OneShotShelve / TimedShelve / Unshelve, threading User/Comment/UnshelveAtUtc) and publish via the DPS mediator. - IAdminOperationsClient + AdminOperationsClient: typed Acknowledge/Shelve ask wrappers mirroring StartDeploymentAsync. - Alerts.razor: per-row DriverOperator-gated Ack/Shelve/Unshelve controls; operator name from AuthenticationState. Timed-shelve datetime UI deferred. - 5 TestKit tests (mediator-probe subscribed to alarm-commands) verifying each kind's mapping + reply; 56/56 ControlPlane tests green.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Commons.Messages.Admin;
|
||||
|
||||
/// <summary>
|
||||
/// AdminUI → AdminOperationsActor: acknowledge one alarm on behalf of an operator. The admin
|
||||
/// singleton maps this to a <c>Commons.OpcUa.AlarmCommand</c> with <c>Operation = "Acknowledge"</c>
|
||||
/// and republishes it onto the cluster <c>alarm-commands</c> topic, where the owning
|
||||
/// <c>ScriptedAlarmHostActor</c> filters by ownership and drives the engine. Routing this through
|
||||
/// the admin-pinned singleton lets the AdminUI act without knowing which node owns the alarm —
|
||||
/// the broadcast + ownership filter handle cross-node delivery.
|
||||
/// </summary>
|
||||
/// <param name="AlarmId">The alarm's ScriptedAlarmId (the <c>AlarmTransitionEvent.AlarmId</c> shown on the row).</param>
|
||||
/// <param name="User">The authenticated operator who triggered the acknowledgement.</param>
|
||||
/// <param name="Comment">Optional free-text comment supplied with the acknowledgement; null when none.</param>
|
||||
/// <param name="CorrelationId">Round-trip correlation token.</param>
|
||||
public sealed record AcknowledgeAlarmCommand(
|
||||
string AlarmId,
|
||||
string User,
|
||||
string? Comment,
|
||||
Guid CorrelationId);
|
||||
|
||||
/// <summary>Reply for <see cref="AcknowledgeAlarmCommand"/>.</summary>
|
||||
/// <param name="Ok">True iff the command was published without error.</param>
|
||||
/// <param name="Message">Failure reason; null on success.</param>
|
||||
/// <param name="CorrelationId">Echoes the request's correlation token.</param>
|
||||
public sealed record AcknowledgeAlarmResult(
|
||||
bool Ok,
|
||||
string? Message,
|
||||
Guid CorrelationId);
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Commons.Messages.Admin;
|
||||
|
||||
/// <summary>
|
||||
/// The shelve action an operator requested. Maps 1:1 onto the engine-side <c>Operation</c>
|
||||
/// strings the <c>ScriptedAlarmHostActor</c> dispatches on
|
||||
/// (<c>OneShotShelve</c> / <c>TimedShelve</c> / <c>Unshelve</c>).
|
||||
/// </summary>
|
||||
public enum ShelveKind
|
||||
{
|
||||
/// <summary>Shelve until the next clear (no timer). Maps to <c>Operation = "OneShotShelve"</c>.</summary>
|
||||
OneShot,
|
||||
|
||||
/// <summary>Shelve until an absolute instant. Maps to <c>Operation = "TimedShelve"</c>; carries <c>UnshelveAtUtc</c>.</summary>
|
||||
Timed,
|
||||
|
||||
/// <summary>Remove an existing shelve. Maps to <c>Operation = "Unshelve"</c>.</summary>
|
||||
Unshelve,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AdminUI → AdminOperationsActor: shelve / unshelve one alarm on behalf of an operator. The admin
|
||||
/// singleton maps <see cref="Kind"/> to the matching <c>Commons.OpcUa.AlarmCommand</c> operation
|
||||
/// (<c>OneShotShelve</c> / <c>TimedShelve</c> / <c>Unshelve</c>), threading
|
||||
/// <see cref="UnshelveAtUtc"/> for <see cref="ShelveKind.Timed"/>, and republishes it onto the
|
||||
/// cluster <c>alarm-commands</c> topic, where the owning <c>ScriptedAlarmHostActor</c> filters by
|
||||
/// ownership and drives the engine.
|
||||
/// </summary>
|
||||
/// <param name="AlarmId">The alarm's ScriptedAlarmId (the <c>AlarmTransitionEvent.AlarmId</c> shown on the row).</param>
|
||||
/// <param name="User">The authenticated operator who triggered the shelve.</param>
|
||||
/// <param name="Kind">Which shelve action to perform.</param>
|
||||
/// <param name="UnshelveAtUtc">
|
||||
/// For <see cref="ShelveKind.Timed"/>, the absolute UTC instant the shelve auto-expires; null for
|
||||
/// <see cref="ShelveKind.OneShot"/> and <see cref="ShelveKind.Unshelve"/>.
|
||||
/// </param>
|
||||
/// <param name="Comment">Optional free-text comment supplied with the shelve; null when none.</param>
|
||||
/// <param name="CorrelationId">Round-trip correlation token.</param>
|
||||
public sealed record ShelveAlarmCommand(
|
||||
string AlarmId,
|
||||
string User,
|
||||
ShelveKind Kind,
|
||||
DateTime? UnshelveAtUtc,
|
||||
string? Comment,
|
||||
Guid CorrelationId);
|
||||
|
||||
/// <summary>Reply for <see cref="ShelveAlarmCommand"/>.</summary>
|
||||
/// <param name="Ok">True iff the command was published without error.</param>
|
||||
/// <param name="Message">Failure reason; null on success.</param>
|
||||
/// <param name="CorrelationId">Echoes the request's correlation token.</param>
|
||||
public sealed record ShelveAlarmResult(
|
||||
bool Ok,
|
||||
string? Message,
|
||||
Guid CorrelationId);
|
||||
Reference in New Issue
Block a user