refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj, namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated. ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated. SQL roles/logins, LDAP domains, CLI command name, and CLI config dir (~/.scadalink → ~/.scadabridge) also renamed. Build green; 5 Host.Tests fail awaiting SQL login rename in next commit. Pre-existing StaleTagMonitor timing flakes unchanged. Rename script committed at tools/rename-to-scadabridge.sh.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
public record ArtifactDeploymentResponse(
|
||||
string DeploymentId,
|
||||
string SiteId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
public record DataConnectionArtifact(
|
||||
string Name,
|
||||
string Protocol,
|
||||
string? PrimaryConfigurationJson,
|
||||
string? BackupConfigurationJson,
|
||||
int FailoverRetryCount = 3);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
public record DatabaseConnectionArtifact(
|
||||
string Name,
|
||||
string ConnectionString,
|
||||
int MaxRetries,
|
||||
TimeSpan RetryDelay);
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
public record DeployArtifactsCommand(
|
||||
string DeploymentId,
|
||||
IReadOnlyList<SharedScriptArtifact>? SharedScripts,
|
||||
IReadOnlyList<ExternalSystemArtifact>? ExternalSystems,
|
||||
IReadOnlyList<DatabaseConnectionArtifact>? DatabaseConnections,
|
||||
IReadOnlyList<NotificationListArtifact>? NotificationLists,
|
||||
IReadOnlyList<DataConnectionArtifact>? DataConnections,
|
||||
IReadOnlyList<SmtpConfigurationArtifact>? SmtpConfigurations,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
public record ExternalSystemArtifact(
|
||||
string Name,
|
||||
string EndpointUrl,
|
||||
string AuthType,
|
||||
string? AuthConfiguration,
|
||||
string? MethodDefinitionsJson);
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
public record NotificationListArtifact(
|
||||
string Name,
|
||||
IReadOnlyList<string> RecipientEmails);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
public record SharedScriptArtifact(
|
||||
string Name,
|
||||
string Code,
|
||||
string? ParameterDefinitions,
|
||||
string? ReturnDefinition);
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts;
|
||||
|
||||
public record SmtpConfigurationArtifact(
|
||||
string Name,
|
||||
string Server,
|
||||
int Port,
|
||||
string AuthMode,
|
||||
string FromAddress,
|
||||
string? Username,
|
||||
string? Password,
|
||||
string? OAuthConfig);
|
||||
@@ -0,0 +1,20 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Akka message sent to the central <c>AuditLogIngestActor</c> (Audit Log #23,
|
||||
/// M2 site-sync pipeline) carrying a batch of <see cref="AuditEvent"/> rows
|
||||
/// decoded by the <c>SiteStreamGrpcServer</c> from a site's
|
||||
/// <c>IngestAuditEvents</c> gRPC RPC. The actor stamps
|
||||
/// <see cref="AuditEvent.IngestedAtUtc"/> and writes the rows idempotently to
|
||||
/// the central <c>AuditLog</c> table.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Lives in <c>ZB.MOM.WW.ScadaBridge.Commons</c> rather than <c>ZB.MOM.WW.ScadaBridge.AuditLog</c>
|
||||
/// because the gRPC server in <c>ZB.MOM.WW.ScadaBridge.Communication</c> needs to construct
|
||||
/// it, and <c>ZB.MOM.WW.ScadaBridge.AuditLog</c> already references
|
||||
/// <c>ZB.MOM.WW.ScadaBridge.Communication</c> (the proto DTOs live there). Putting the
|
||||
/// message in Commons avoids a project-reference cycle.
|
||||
/// </remarks>
|
||||
public sealed record IngestAuditEventsCommand(IReadOnlyList<AuditEvent> Events);
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Reply from the central <c>AuditLogIngestActor</c> for an
|
||||
/// <see cref="IngestAuditEventsCommand"/>. <see cref="AcceptedEventIds"/> lists
|
||||
/// every row the actor considers durably persisted at central — including ids
|
||||
/// that were already present before the call (first-write-wins idempotency).
|
||||
/// The gRPC handler echoes these ids back over the wire as the <c>IngestAck</c>
|
||||
/// the site uses to flip rows to <c>Forwarded</c>.
|
||||
/// </summary>
|
||||
public sealed record IngestAuditEventsReply(IReadOnlyList<Guid> AcceptedEventIds);
|
||||
@@ -0,0 +1,30 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Akka message sent to the central <c>AuditLogIngestActor</c> (Audit Log #23 M3
|
||||
/// Bundle D dual-write transaction) carrying a batch of combined audit +
|
||||
/// site-call telemetry packets decoded by the <c>SiteStreamGrpcServer</c> from a
|
||||
/// site's <c>IngestCachedTelemetry</c> gRPC RPC. For each entry the actor writes
|
||||
/// the <see cref="AuditEvent"/> row AND the <see cref="SiteCall"/> upsert inside
|
||||
/// a single MS SQL transaction — both succeed or both roll back, so the audit
|
||||
/// and operational mirrors never drift mid-row.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Lives in <c>ZB.MOM.WW.ScadaBridge.Commons</c> for the same reason as
|
||||
/// <c>IngestAuditEventsCommand</c>: the gRPC server in
|
||||
/// <c>ZB.MOM.WW.ScadaBridge.Communication</c> constructs it and <c>ZB.MOM.WW.ScadaBridge.AuditLog</c>
|
||||
/// already references Communication. Putting the message in Commons avoids a
|
||||
/// project-reference cycle.
|
||||
/// </remarks>
|
||||
public sealed record IngestCachedTelemetryCommand(IReadOnlyList<CachedTelemetryEntry> Entries);
|
||||
|
||||
/// <summary>
|
||||
/// One lifecycle event of a cached call: the <see cref="AuditEvent"/> to insert
|
||||
/// (idempotent on <see cref="AuditEvent.EventId"/>) plus the
|
||||
/// <see cref="SiteCall"/> to upsert (monotonic on
|
||||
/// <see cref="SiteCall.TrackedOperationId"/>). The two rows are paired so the
|
||||
/// central dual-write transaction can commit them atomically.
|
||||
/// </summary>
|
||||
public sealed record CachedTelemetryEntry(AuditEvent Audit, SiteCall SiteCall);
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Reply from the central <c>AuditLogIngestActor</c> for an
|
||||
/// <see cref="IngestCachedTelemetryCommand"/>. <see cref="AcceptedEventIds"/>
|
||||
/// lists every entry whose dual-write transaction (AuditLog INSERT + SiteCalls
|
||||
/// UPSERT) committed; entries whose transaction rolled back are absent so the
|
||||
/// site can leave the row Pending and retry on the next drain.
|
||||
/// </summary>
|
||||
public sealed record IngestCachedTelemetryReply(IReadOnlyList<Guid> AcceptedEventIds);
|
||||
@@ -0,0 +1,166 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Site Calls UI -> Central: paginated, filtered query over the central
|
||||
/// <c>SiteCalls</c> table (Site Call Audit #22). All filter fields are optional;
|
||||
/// <see cref="StuckOnly"/> restricts results to stuck cached calls. Mirrors
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Messages.Notification.NotificationOutboxQueryRequest"/>
|
||||
/// but uses keyset paging (<see cref="AfterCreatedAtUtc"/> + <see cref="AfterId"/>)
|
||||
/// to match the repository's <c>(CreatedAtUtc DESC, TrackedOperationId DESC)</c>
|
||||
/// cursor, rather than page numbers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="ChannelFilter"/> matches the <c>SiteCall.Channel</c> column —
|
||||
/// <c>"ApiOutbound"</c> or <c>"DbOutbound"</c> (the spec's <c>Kind</c> notion;
|
||||
/// the entity exposes it as <c>Channel</c>). <see cref="TargetKeyword"/> is an
|
||||
/// exact-match target filter, consistent with the repository's
|
||||
/// <see cref="SiteCallQueryFilter.Target"/> predicate.
|
||||
/// </remarks>
|
||||
/// <param name="PageSize">
|
||||
/// Requested page size. The actor clamps this to the <c>[1, 200]</c> range, so
|
||||
/// the effective ceiling is 200 rows per page regardless of the value sent.
|
||||
/// </param>
|
||||
public sealed record SiteCallQueryRequest(
|
||||
string CorrelationId,
|
||||
string? StatusFilter,
|
||||
string? SourceSiteFilter,
|
||||
string? ChannelFilter,
|
||||
string? TargetKeyword,
|
||||
bool StuckOnly,
|
||||
DateTime? FromUtc,
|
||||
DateTime? ToUtc,
|
||||
DateTime? AfterCreatedAtUtc,
|
||||
Guid? AfterId,
|
||||
int PageSize,
|
||||
string? SourceNodeFilter = null);
|
||||
|
||||
/// <summary>
|
||||
/// A single <c>SiteCalls</c> row summarised for the Site Calls UI grid. Carries
|
||||
/// only the columns the <see cref="ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit.SiteCall"/>
|
||||
/// entity genuinely exposes — there are no source-instance/script provenance
|
||||
/// columns on that entity, so unlike
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Messages.Notification.NotificationSummary"/>
|
||||
/// none are surfaced here.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="HttpStatus"/> is not called out in the Site Call Audit plan, but
|
||||
/// it is a real (nullable) <see cref="ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit.SiteCall"/>
|
||||
/// column — the last HTTP status code observed for the call — so it is surfaced
|
||||
/// here for the grid; <c>null</c> for non-HTTP channels or before a first attempt.
|
||||
/// </remarks>
|
||||
public sealed record SiteCallSummary(
|
||||
Guid TrackedOperationId,
|
||||
string SourceSite,
|
||||
string Channel,
|
||||
string Target,
|
||||
string Status,
|
||||
int RetryCount,
|
||||
string? LastError,
|
||||
int? HttpStatus,
|
||||
DateTime CreatedAtUtc,
|
||||
DateTime UpdatedAtUtc,
|
||||
DateTime? TerminalAtUtc,
|
||||
bool IsStuck,
|
||||
string? SourceNode = null);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Site Calls UI: paginated response for a <see cref="SiteCallQueryRequest"/>.
|
||||
/// The keyset cursor of the last row is echoed back as
|
||||
/// <see cref="NextAfterCreatedAtUtc"/> + <see cref="NextAfterId"/> for the caller
|
||||
/// to request the following page; both are <c>null</c> when the page was empty.
|
||||
/// On a repository fault <see cref="Success"/> is <c>false</c>,
|
||||
/// <see cref="ErrorMessage"/> carries the cause and <see cref="SiteCalls"/> is empty.
|
||||
/// </summary>
|
||||
public sealed record SiteCallQueryResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
IReadOnlyList<SiteCallSummary> SiteCalls,
|
||||
DateTime? NextAfterCreatedAtUtc,
|
||||
Guid? NextAfterId);
|
||||
|
||||
/// <summary>
|
||||
/// Site Calls UI -> Central: request for the full detail of a single cached call,
|
||||
/// for the report detail modal.
|
||||
/// </summary>
|
||||
public sealed record SiteCallDetailRequest(
|
||||
string CorrelationId,
|
||||
Guid TrackedOperationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Site Calls UI: full detail for one cached call. On a repository
|
||||
/// fault or missing row, <see cref="Success"/> is <c>false</c> /
|
||||
/// <see cref="Detail"/> is <c>null</c> and <see cref="ErrorMessage"/> carries
|
||||
/// the cause.
|
||||
/// </summary>
|
||||
public sealed record SiteCallDetailResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
SiteCallDetail? Detail);
|
||||
|
||||
/// <summary>
|
||||
/// Full <c>SiteCalls</c> row detail for the report detail modal — every field
|
||||
/// on the <see cref="ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit.SiteCall"/> entity,
|
||||
/// including <see cref="LastError"/> and the <see cref="IngestedAtUtc"/>
|
||||
/// timestamp the grid summary omits.
|
||||
/// </summary>
|
||||
public sealed record SiteCallDetail(
|
||||
Guid TrackedOperationId,
|
||||
string SourceSite,
|
||||
string Channel,
|
||||
string Target,
|
||||
string Status,
|
||||
int RetryCount,
|
||||
string? LastError,
|
||||
int? HttpStatus,
|
||||
DateTime CreatedAtUtc,
|
||||
DateTime UpdatedAtUtc,
|
||||
DateTime? TerminalAtUtc,
|
||||
DateTime IngestedAtUtc,
|
||||
string? SourceNode = null);
|
||||
|
||||
/// <summary>
|
||||
/// Site Calls UI -> Central: request for the global <c>SiteCalls</c> KPI summary.
|
||||
/// Mirrors <see cref="ZB.MOM.WW.ScadaBridge.Commons.Messages.Notification.NotificationKpiRequest"/>.
|
||||
/// </summary>
|
||||
public sealed record SiteCallKpiRequest(
|
||||
string CorrelationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Site Calls UI: KPI summary for the Site Calls dashboard. On a
|
||||
/// repository fault <see cref="Success"/> is <c>false</c>,
|
||||
/// <see cref="ErrorMessage"/> carries the cause, and the KPI fields are
|
||||
/// zeroed/<c>null</c>.
|
||||
/// </summary>
|
||||
public sealed record SiteCallKpiResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
int BufferedCount,
|
||||
int ParkedCount,
|
||||
int FailedLastInterval,
|
||||
int DeliveredLastInterval,
|
||||
TimeSpan? OldestPendingAge,
|
||||
int StuckCount);
|
||||
|
||||
/// <summary>
|
||||
/// Site Calls UI -> Central: request for the per-source-site <c>SiteCalls</c>
|
||||
/// KPI breakdown. Mirrors
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Messages.Notification.PerSiteNotificationKpiRequest"/>.
|
||||
/// </summary>
|
||||
public sealed record PerSiteSiteCallKpiRequest(
|
||||
string CorrelationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Site Calls UI: per-site KPI breakdown for the Site Calls KPIs
|
||||
/// page. On a repository fault <see cref="Success"/> is <c>false</c>,
|
||||
/// <see cref="ErrorMessage"/> carries the cause, and <see cref="Sites"/> is empty.
|
||||
/// </summary>
|
||||
public sealed record PerSiteSiteCallKpiResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
IReadOnlyList<SiteCallSiteKpiSnapshot> Sites);
|
||||
@@ -0,0 +1,113 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Outcome of a Site Call Audit (#22) Retry/Discard relay — distinguishes the
|
||||
/// three cases the Central UI Site Calls page must surface differently.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The "site unreachable" case is deliberately separate from
|
||||
/// <see cref="OperationFailed"/>: central is an eventually-consistent mirror,
|
||||
/// not the source of truth, so a relay that never reaches the owning site is a
|
||||
/// transient transport condition the operator can retry — not a failed
|
||||
/// operation. The UI shows "site unreachable" rather than a generic error.
|
||||
/// </remarks>
|
||||
public enum SiteCallRelayOutcome
|
||||
{
|
||||
/// <summary>
|
||||
/// The owning site received the relay command and applied the action to its
|
||||
/// Store-and-Forward buffer (the parked cached call was reset to retry, or
|
||||
/// discarded). The corrected state reaches central later via telemetry.
|
||||
/// </summary>
|
||||
Applied,
|
||||
|
||||
/// <summary>
|
||||
/// The owning site received the relay command but found nothing to do — no
|
||||
/// parked row matched the tracked id (already delivered/discarded, or no
|
||||
/// longer <c>Parked</c>). A definitive answer from the site, not a failure.
|
||||
/// </summary>
|
||||
NotParked,
|
||||
|
||||
/// <summary>
|
||||
/// The owning site could not be reached (offline / no ClusterClient route /
|
||||
/// relay timed out). The action was NOT applied; the operator may retry once
|
||||
/// the site is back online.
|
||||
/// </summary>
|
||||
SiteUnreachable,
|
||||
|
||||
/// <summary>
|
||||
/// The owning site was reached but reported it could not apply the action
|
||||
/// (its parked-message handler was unavailable or its store faulted).
|
||||
/// </summary>
|
||||
OperationFailed,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Central UI → Site Call Audit: relay a Retry of a parked cached call to its
|
||||
/// owning site. The owning site performs the actual retry on its
|
||||
/// Store-and-Forward buffer — central never mutates the central <c>SiteCalls</c>
|
||||
/// mirror row. Mirrors
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.Commons.Messages.Notification.RetryNotificationRequest"/>
|
||||
/// but carries <see cref="SourceSite"/> (the relay target) and answers with a
|
||||
/// distinct site-unreachable outcome.
|
||||
/// </summary>
|
||||
/// <param name="CorrelationId">Request correlation id, echoed on the response.</param>
|
||||
/// <param name="TrackedOperationId">
|
||||
/// The cached operation to retry — the PK of the central <c>SiteCalls</c> row
|
||||
/// and the S&F buffer message id at the owning site.
|
||||
/// </param>
|
||||
/// <param name="SourceSite">
|
||||
/// The owning site (<c>SiteCall.SourceSite</c>) the relay is routed to.
|
||||
/// </param>
|
||||
public sealed record RetrySiteCallRequest(
|
||||
string CorrelationId,
|
||||
Guid TrackedOperationId,
|
||||
string SourceSite);
|
||||
|
||||
/// <summary>
|
||||
/// Site Call Audit → Central UI: result of a <see cref="RetrySiteCallRequest"/>.
|
||||
/// </summary>
|
||||
/// <param name="CorrelationId">Echoed request correlation id.</param>
|
||||
/// <param name="Outcome">
|
||||
/// The relay outcome — <see cref="SiteCallRelayOutcome.Applied"/>,
|
||||
/// <see cref="SiteCallRelayOutcome.NotParked"/>,
|
||||
/// <see cref="SiteCallRelayOutcome.SiteUnreachable"/> or
|
||||
/// <see cref="SiteCallRelayOutcome.OperationFailed"/>.
|
||||
/// </param>
|
||||
/// <param name="Success">
|
||||
/// Convenience flag — <c>true</c> only for <see cref="SiteCallRelayOutcome.Applied"/>.
|
||||
/// </param>
|
||||
/// <param name="SiteReachable">
|
||||
/// <c>false</c> only for <see cref="SiteCallRelayOutcome.SiteUnreachable"/>; lets
|
||||
/// the UI distinguish "site offline" from "operation failed" without switching
|
||||
/// on the enum.
|
||||
/// </param>
|
||||
/// <param name="ErrorMessage">
|
||||
/// Human-readable detail for a non-applied outcome; <c>null</c> on success.
|
||||
/// </param>
|
||||
public sealed record RetrySiteCallResponse(
|
||||
string CorrelationId,
|
||||
SiteCallRelayOutcome Outcome,
|
||||
bool Success,
|
||||
bool SiteReachable,
|
||||
string? ErrorMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Central UI → Site Call Audit: relay a Discard of a parked cached call to its
|
||||
/// owning site. See <see cref="RetrySiteCallRequest"/> for the source-of-truth
|
||||
/// and routing rationale.
|
||||
/// </summary>
|
||||
public sealed record DiscardSiteCallRequest(
|
||||
string CorrelationId,
|
||||
Guid TrackedOperationId,
|
||||
string SourceSite);
|
||||
|
||||
/// <summary>
|
||||
/// Site Call Audit → Central UI: result of a <see cref="DiscardSiteCallRequest"/>.
|
||||
/// Same shape as <see cref="RetrySiteCallResponse"/>.
|
||||
/// </summary>
|
||||
public sealed record DiscardSiteCallResponse(
|
||||
string CorrelationId,
|
||||
SiteCallRelayOutcome Outcome,
|
||||
bool Success,
|
||||
bool SiteReachable,
|
||||
string? ErrorMessage);
|
||||
@@ -0,0 +1,19 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Akka message sent to the central <c>SiteCallAuditActor</c> (Site Call Audit
|
||||
/// #22, Audit Log #23 M3 Bundle C) carrying one <see cref="SiteCall"/> row to
|
||||
/// be persisted via <c>ISiteCallAuditRepository.UpsertAsync</c>. The repository
|
||||
/// performs an insert-if-not-exists then monotonic update — duplicate gRPC
|
||||
/// packets and reconciliation pulls can both feed the actor without rolling
|
||||
/// state back.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Lives in <c>ZB.MOM.WW.ScadaBridge.Commons</c> rather than <c>ZB.MOM.WW.ScadaBridge.SiteCallAudit</c>
|
||||
/// so the gRPC server in <c>ZB.MOM.WW.ScadaBridge.Communication</c> can construct it
|
||||
/// without taking a project reference on the actor's host project (Bundle D
|
||||
/// adds the IngestCachedTelemetry RPC that will Tell this command).
|
||||
/// </remarks>
|
||||
public sealed record UpsertSiteCallCommand(SiteCall SiteCall);
|
||||
@@ -0,0 +1,14 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Reply from the central <c>SiteCallAuditActor</c> for an
|
||||
/// <see cref="UpsertSiteCallCommand"/>. <see cref="Accepted"/> is <c>true</c>
|
||||
/// when the upsert reached the repository without throwing (including the
|
||||
/// monotonic-no-op case where the stored status' rank wins) and <c>false</c>
|
||||
/// when persistence raised an exception. The actor itself stays alive in
|
||||
/// either case — audit-write failures must NEVER abort the user-facing action
|
||||
/// (Audit Log #23 §13).
|
||||
/// </summary>
|
||||
public sealed record UpsertSiteCallReply(TrackedOperationId TrackedOperationId, bool Accepted);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Communication;
|
||||
|
||||
public record RoutingMetadata(
|
||||
string TargetSiteId,
|
||||
string? TargetInstanceUniqueName,
|
||||
string CorrelationId);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Communication;
|
||||
|
||||
public record SiteIdentity(
|
||||
string SiteId,
|
||||
string NodeHostname,
|
||||
bool IsActive);
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// Command to create a new data connection actor for a specific protocol.
|
||||
/// Sent from DeploymentManagerActor to DCL Manager Actor.
|
||||
/// </summary>
|
||||
public record CreateConnectionCommand(
|
||||
string ConnectionName,
|
||||
string ProtocolType,
|
||||
IDictionary<string, string> PrimaryConnectionDetails,
|
||||
IDictionary<string, string>? BackupConnectionDetails = null,
|
||||
int FailoverRetryCount = 3);
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// Health metrics for a single data connection, contributed to the site health report.
|
||||
/// </summary>
|
||||
public record DataConnectionHealthReport(
|
||||
string ConnectionName,
|
||||
ConnectionHealth Status,
|
||||
int TotalSubscribedTags,
|
||||
int ResolvedTags,
|
||||
string ActiveEndpoint,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// Request from an Instance Actor to subscribe to tag values through the DCL.
|
||||
/// </summary>
|
||||
public record SubscribeTagsRequest(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
string ConnectionName,
|
||||
IReadOnlyList<string> TagPaths,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// Response confirming tag subscription registration.
|
||||
/// </summary>
|
||||
public record SubscribeTagsResponse(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,21 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Protocol;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// Published by DCL to an Instance Actor when a subscribed tag value changes.
|
||||
/// </summary>
|
||||
public record TagValueUpdate(
|
||||
string ConnectionName,
|
||||
string TagPath,
|
||||
object? Value,
|
||||
QualityCode Quality,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Published by DCL when connection state changes, causing bulk quality updates.
|
||||
/// </summary>
|
||||
public record ConnectionQualityChanged(
|
||||
string ConnectionName,
|
||||
QualityCode Quality,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// Request from an Instance Actor to unsubscribe from all its tags when stopping.
|
||||
/// </summary>
|
||||
public record UnsubscribeTagsRequest(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
string ConnectionName,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// Request to write a value to a device tag through the DCL.
|
||||
/// Write failures are returned synchronously to the calling script.
|
||||
/// </summary>
|
||||
public record WriteTagRequest(
|
||||
string CorrelationId,
|
||||
string ConnectionName,
|
||||
string TagPath,
|
||||
object? Value,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Response for a device tag write operation.
|
||||
/// </summary>
|
||||
public record WriteTagResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DebugView;
|
||||
|
||||
public record DebugSnapshotRequest(
|
||||
string InstanceUniqueName,
|
||||
string CorrelationId);
|
||||
@@ -0,0 +1,9 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Messages.Streaming;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DebugView;
|
||||
|
||||
public record DebugViewSnapshot(
|
||||
string InstanceUniqueName,
|
||||
IReadOnlyList<AttributeValueChanged> AttributeValues,
|
||||
IReadOnlyList<AlarmStateChanged> AlarmStates,
|
||||
DateTimeOffset SnapshotTimestamp);
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DebugView;
|
||||
|
||||
public record SubscribeDebugViewRequest(
|
||||
string InstanceUniqueName,
|
||||
string CorrelationId);
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.DebugView;
|
||||
|
||||
public record UnsubscribeDebugViewRequest(
|
||||
string InstanceUniqueName,
|
||||
string CorrelationId);
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Deployment;
|
||||
|
||||
public record DeployInstanceCommand(
|
||||
string DeploymentId,
|
||||
string InstanceUniqueName,
|
||||
string RevisionHash,
|
||||
string FlattenedConfigurationJson,
|
||||
string DeployedBy,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Deployment;
|
||||
|
||||
/// <summary>
|
||||
/// Central→site query for the currently-applied deployment state of a single
|
||||
/// instance. Issued by the Deployment Manager before a re-deploy when a prior
|
||||
/// deployment record is stuck <c>InProgress</c> or <c>Failed</c> due to a
|
||||
/// timeout, so the site's actual state can be reconciled against the target
|
||||
/// revision before re-sending a deployment ("Deployment Identity & Idempotency").
|
||||
/// </summary>
|
||||
public record DeploymentStateQueryRequest(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Deployment;
|
||||
|
||||
/// <summary>
|
||||
/// Site→central response carrying the instance's currently-applied deployment
|
||||
/// state. If <see cref="IsDeployed"/> is <c>false</c> the instance has no
|
||||
/// deployed configuration at the site and <see cref="AppliedDeploymentId"/> /
|
||||
/// <see cref="AppliedRevisionHash"/> are <c>null</c>.
|
||||
/// </summary>
|
||||
public record DeploymentStateQueryResponse(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
bool IsDeployed,
|
||||
string? AppliedDeploymentId,
|
||||
string? AppliedRevisionHash,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,10 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Deployment;
|
||||
|
||||
public record DeploymentStatusResponse(
|
||||
string DeploymentId,
|
||||
string InstanceUniqueName,
|
||||
DeploymentStatus Status,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Deployment;
|
||||
|
||||
public record DeploymentValidationResult(
|
||||
bool IsValid,
|
||||
IReadOnlyList<string> Errors,
|
||||
IReadOnlyList<string> Warnings);
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Deployment;
|
||||
|
||||
public record FlattenedConfigurationSnapshot(
|
||||
string InstanceUniqueName,
|
||||
string RevisionHash,
|
||||
string ConfigurationJson,
|
||||
DateTimeOffset GeneratedAt);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Health;
|
||||
|
||||
public record HeartbeatMessage(
|
||||
string SiteId,
|
||||
string NodeHostname,
|
||||
bool IsActive,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Health;
|
||||
|
||||
public record NodeStatus(string Hostname, bool IsOnline, string Role);
|
||||
@@ -0,0 +1,53 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Health;
|
||||
|
||||
public record SiteHealthReport(
|
||||
string SiteId,
|
||||
long SequenceNumber,
|
||||
DateTimeOffset ReportTimestamp,
|
||||
IReadOnlyDictionary<string, ConnectionHealth> DataConnectionStatuses,
|
||||
IReadOnlyDictionary<string, TagResolutionStatus> TagResolutionCounts,
|
||||
int ScriptErrorCount,
|
||||
int AlarmEvaluationErrorCount,
|
||||
IReadOnlyDictionary<string, int> StoreAndForwardBufferDepths,
|
||||
int DeadLetterCount,
|
||||
int DeployedInstanceCount,
|
||||
int EnabledInstanceCount,
|
||||
int DisabledInstanceCount,
|
||||
string NodeRole = "Unknown",
|
||||
string NodeHostname = "",
|
||||
IReadOnlyDictionary<string, string>? DataConnectionEndpoints = null,
|
||||
IReadOnlyDictionary<string, TagQualityCounts>? DataConnectionTagQuality = null,
|
||||
int ParkedMessageCount = 0,
|
||||
IReadOnlyList<NodeStatus>? ClusterNodes = null,
|
||||
// Audit Log (#23) M2 Bundle G: per-interval count of FallbackAuditWriter
|
||||
// primary failures (SQLite throws routed to the drop-oldest ring). Surfaces
|
||||
// a sustained audit-write outage on /monitoring/health. Defaults to 0 so
|
||||
// existing producers / tests that don't construct the field stay valid.
|
||||
int SiteAuditWriteFailures = 0,
|
||||
// Audit Log (#23) M5 Bundle C: per-interval count of payload-filter
|
||||
// redactor over-redactions (header / body / SQL parameter stages all
|
||||
// throwing → field replaced with the "<redacted: redactor error>"
|
||||
// marker). Surfaces a misconfigured / catastrophic regex on
|
||||
// /monitoring/health. Defaults to 0 for back-compat with existing
|
||||
// producers and tests that don't construct the field.
|
||||
int AuditRedactionFailure = 0,
|
||||
// Audit Log (#23) M6 Bundle E (T6): point-in-time snapshot of the
|
||||
// site-local SQLite audit-log queue (pending count, oldest pending row,
|
||||
// on-disk bytes). Populated by the site-side SiteAuditBacklogReporter
|
||||
// hosted service every 30 s. Defaults to null so existing producers /
|
||||
// tests that don't refresh the snapshot stay valid; the central health
|
||||
// surface treats null as "no data yet" rather than a zeroed queue.
|
||||
SiteAuditBacklogSnapshot? SiteAuditBacklog = null);
|
||||
|
||||
/// <summary>
|
||||
/// Broadcast wrapper used between central nodes to keep per-node
|
||||
/// CentralHealthAggregator state in sync. ClusterClient load-balances each
|
||||
/// incoming SiteHealthReport to one central node; that node re-publishes
|
||||
/// this wrapper on a DistributedPubSub topic so the peer node's aggregator
|
||||
/// also processes the report (idempotently — sequence numbers guard against
|
||||
/// double-counting).
|
||||
/// </summary>
|
||||
public record SiteHealthReportReplica(SiteHealthReport Report);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Health;
|
||||
|
||||
public record TagQualityCounts(int Good, int Bad, int Uncertain);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Health;
|
||||
|
||||
public record TagResolutionStatus(int TotalSubscribed, int SuccessfullyResolved);
|
||||
@@ -0,0 +1,85 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.InboundApi;
|
||||
|
||||
/// <summary>
|
||||
/// Request routed from Inbound API to a site to invoke a script on an instance.
|
||||
/// Used by Route.To("instanceCode").Call("scriptName", params).
|
||||
/// </summary>
|
||||
/// <param name="ParentExecutionId">
|
||||
/// Audit Log #23 (ParentExecutionId): the spawning execution's <c>ExecutionId</c>
|
||||
/// — for an inbound-API-routed call this is the inbound request's per-request
|
||||
/// execution id. The site records it as the routed script execution's
|
||||
/// <c>ParentExecutionId</c> so a spawned execution points back at its spawner.
|
||||
/// Additive trailing member — null for requests built before the field existed
|
||||
/// or for routed calls with no spawning execution (e.g. the Central UI sandbox).
|
||||
/// </param>
|
||||
public record RouteToCallRequest(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
string ScriptName,
|
||||
IReadOnlyDictionary<string, object?>? Parameters,
|
||||
DateTimeOffset Timestamp,
|
||||
Guid? ParentExecutionId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Response from a Route.To() call.
|
||||
/// </summary>
|
||||
public record RouteToCallResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
object? ReturnValue,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Request to read attribute(s) from a remote instance.
|
||||
/// </summary>
|
||||
/// <param name="ParentExecutionId">
|
||||
/// Audit Log #23 (ParentExecutionId): mirrors <see cref="RouteToCallRequest.ParentExecutionId"/>.
|
||||
/// For an inbound-API-routed read this is the inbound request's per-request execution id;
|
||||
/// future site-side audit emission for routed reads can stamp it as <c>ParentExecutionId</c>
|
||||
/// so the inbound→site execution-tree link survives the read path. Additive trailing
|
||||
/// member — null for the Central UI sandbox path or for callers built before the field existed.
|
||||
/// </param>
|
||||
public record RouteToGetAttributesRequest(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
IReadOnlyList<string> AttributeNames,
|
||||
DateTimeOffset Timestamp,
|
||||
Guid? ParentExecutionId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Response containing attribute values from a remote instance.
|
||||
/// </summary>
|
||||
public record RouteToGetAttributesResponse(
|
||||
string CorrelationId,
|
||||
IReadOnlyDictionary<string, object?> Values,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Request to write attribute(s) on a remote instance.
|
||||
/// </summary>
|
||||
/// <param name="ParentExecutionId">
|
||||
/// Audit Log #23 (ParentExecutionId): mirrors <see cref="RouteToCallRequest.ParentExecutionId"/>.
|
||||
/// For an inbound-API-routed write this is the inbound request's per-request execution id;
|
||||
/// site-side audit emission for the underlying device / static-attribute write can stamp
|
||||
/// it as <c>ParentExecutionId</c> so the inbound→site execution-tree link survives the
|
||||
/// write path. Additive trailing member — null for the Central UI sandbox path or for
|
||||
/// callers built before the field existed.
|
||||
/// </param>
|
||||
public record RouteToSetAttributesRequest(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
IReadOnlyDictionary<string, string> AttributeValues,
|
||||
DateTimeOffset Timestamp,
|
||||
Guid? ParentExecutionId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Response confirming attribute writes on a remote instance.
|
||||
/// </summary>
|
||||
public record RouteToSetAttributesResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Request to get the current value of an attribute from an Instance Actor.
|
||||
/// Uses the Ask pattern for system boundaries; Tell pattern is preferred for hot-path.
|
||||
/// </summary>
|
||||
public record GetAttributeRequest(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
string AttributeName,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Response containing the current value and quality of an attribute.
|
||||
/// Quality is "Good", "Bad", or "Uncertain".
|
||||
/// Data-sourced attributes start at "Uncertain" until the first DCL value update arrives.
|
||||
/// </summary>
|
||||
public record GetAttributeResponse(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
string AttributeName,
|
||||
object? Value,
|
||||
bool Found,
|
||||
string Quality,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Batch request to get multiple attribute values from an Instance Actor.
|
||||
/// Used by Route.To().GetAttributes() in Inbound API.
|
||||
/// </summary>
|
||||
public record GetAttributesBatchRequest(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
IReadOnlyList<string> AttributeNames,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Batch response containing multiple attribute values.
|
||||
/// </summary>
|
||||
public record GetAttributesBatchResponse(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
IReadOnlyDictionary<string, object?> Values,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Batch command to set multiple attribute values on an Instance Actor.
|
||||
/// Used by Route.To().SetAttributes() in Inbound API.
|
||||
/// </summary>
|
||||
public record SetAttributesBatchCommand(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
IReadOnlyDictionary<string, string> AttributeValues,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Batch response confirming multiple attribute writes.
|
||||
/// </summary>
|
||||
public record SetAttributesBatchResponse(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Command to set a static attribute value on an Instance Actor.
|
||||
/// Updates in-memory state and persists the override to SQLite.
|
||||
/// </summary>
|
||||
public record SetStaticAttributeCommand(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
string AttributeName,
|
||||
string Value,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Response confirming that a static attribute was set.
|
||||
/// </summary>
|
||||
public record SetStaticAttributeResponse(
|
||||
string CorrelationId,
|
||||
string InstanceUniqueName,
|
||||
string AttributeName,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,13 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// Audit Log (#23) telemetry envelope sent from a site to central over gRPC.
|
||||
/// At-least-once delivery; central is idempotent on <see cref="AuditEvent.EventId"/>.
|
||||
/// See Component-AuditLog.md "Ingestion" for the handoff contract.
|
||||
/// </summary>
|
||||
public sealed record AuditTelemetryEnvelope(
|
||||
Guid EnvelopeId,
|
||||
string SourceSiteId,
|
||||
IReadOnlyList<AuditEvent> Events);
|
||||
@@ -0,0 +1,34 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// Combined audit + operational telemetry packet for cached outbound calls
|
||||
/// (Audit Log #23 / M3). The site emits one packet per lifecycle event
|
||||
/// — <c>Submit</c> (Audit kind <c>CachedSubmit</c>), per-attempt
|
||||
/// <c>ApiCallCached</c>/<c>DbWriteCached</c>, terminal <c>CachedResolve</c> —
|
||||
/// and central writes the <see cref="AuditEvent"/> row plus the
|
||||
/// <see cref="SiteCallOperational"/> upsert in one MS SQL transaction. Two
|
||||
/// payload shapes ride on a single wire message so the same on-the-wire batch
|
||||
/// can carry mixed lifecycle events without the central dual-write needing a
|
||||
/// second RPC for the operational state.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Both inner records carry the same <c>TrackedOperationId</c> — the
|
||||
/// idempotency key end-to-end. The <see cref="AuditEvent.CorrelationId"/>
|
||||
/// pattern (used by Audit Log #23 to thread cached-call rows together) is
|
||||
/// honoured by the site emitter; the packet itself is shape-only and makes no
|
||||
/// independent correlation guarantees.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Additive-only per Commons REQ-COM-5a (M2 reviewer note) — this is a new
|
||||
/// message, not a rename of any existing M2 envelope.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="Audit">The Audit Log #23 row to insert at central.</param>
|
||||
/// <param name="Operational">The <c>SiteCalls</c> upsert mirroring this lifecycle event.</param>
|
||||
public sealed record CachedCallTelemetry(
|
||||
AuditEvent Audit,
|
||||
SiteCallOperational Operational);
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// Request routed from central to site to invoke an integration method
|
||||
/// (external system call or notification) on behalf of the central UI or API.
|
||||
/// </summary>
|
||||
public record IntegrationCallRequest(
|
||||
string CorrelationId,
|
||||
string SiteId,
|
||||
string InstanceUniqueName,
|
||||
string TargetSystemName,
|
||||
string MethodName,
|
||||
IReadOnlyDictionary<string, object?> Parameters,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// Response for an integration call routed through central-site communication.
|
||||
/// </summary>
|
||||
public record IntegrationCallResponse(
|
||||
string CorrelationId,
|
||||
string SiteId,
|
||||
bool Success,
|
||||
string? ResultJson,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// Audit Log (#23) periodic reconciliation pull request: central asks a site for
|
||||
/// audit events since the given UTC watermark, up to <paramref name="BatchSize"/>.
|
||||
/// Acts as the fallback when streaming telemetry is lost. See Component-AuditLog.md "Ingestion".
|
||||
/// </summary>
|
||||
public sealed record PullAuditEventsRequest(
|
||||
string SourceSiteId,
|
||||
DateTime SinceUtc,
|
||||
int BatchSize);
|
||||
@@ -0,0 +1,12 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// Audit Log (#23) periodic reconciliation pull response: the next batch of site
|
||||
/// audit events plus a <paramref name="MoreAvailable"/> flag signalling the caller
|
||||
/// to advance the watermark and pull again. See Component-AuditLog.md "Ingestion".
|
||||
/// </summary>
|
||||
public sealed record PullAuditEventsResponse(
|
||||
IReadOnlyList<AuditEvent> Events,
|
||||
bool MoreAvailable);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Lifecycle;
|
||||
|
||||
public record DeleteInstanceCommand(
|
||||
string CommandId,
|
||||
string InstanceUniqueName,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Lifecycle;
|
||||
|
||||
public record DisableInstanceCommand(
|
||||
string CommandId,
|
||||
string InstanceUniqueName,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Lifecycle;
|
||||
|
||||
public record EnableInstanceCommand(
|
||||
string CommandId,
|
||||
string InstanceUniqueName,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Lifecycle;
|
||||
|
||||
public record InstanceLifecycleResponse(
|
||||
string CommandId,
|
||||
string InstanceUniqueName,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record QueryAuditLogCommand(
|
||||
string? User = null, string? EntityType = null, string? Action = null,
|
||||
DateTimeOffset? From = null, DateTimeOffset? To = null,
|
||||
int Page = 1, int PageSize = 50);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListDataConnectionsCommand(int? SiteId = null);
|
||||
public record GetDataConnectionCommand(int DataConnectionId);
|
||||
public record CreateDataConnectionCommand(int SiteId, string Name, string Protocol, string? PrimaryConfiguration, string? BackupConfiguration = null, int FailoverRetryCount = 3);
|
||||
public record UpdateDataConnectionCommand(int DataConnectionId, string Name, string Protocol, string? PrimaryConfiguration, string? BackupConfiguration = null, int FailoverRetryCount = 3);
|
||||
public record DeleteDataConnectionCommand(int DataConnectionId);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListDatabaseConnectionsCommand;
|
||||
public record GetDatabaseConnectionCommand(int DatabaseConnectionId);
|
||||
public record CreateDatabaseConnectionDefCommand(string Name, string ConnectionString);
|
||||
public record UpdateDatabaseConnectionDefCommand(int DatabaseConnectionId, string Name, string ConnectionString);
|
||||
public record DeleteDatabaseConnectionDefCommand(int DatabaseConnectionId);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record DebugSnapshotCommand(int InstanceId);
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record MgmtDeployArtifactsCommand(int? SiteId = null);
|
||||
public record QueryDeploymentsCommand(int? InstanceId = null, string? Status = null, int Page = 1, int PageSize = 50);
|
||||
public record GetDeploymentDiffCommand(int InstanceId);
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListExternalSystemsCommand;
|
||||
public record GetExternalSystemCommand(int ExternalSystemId);
|
||||
public record CreateExternalSystemCommand(string Name, string EndpointUrl, string AuthType, string? AuthConfiguration);
|
||||
public record UpdateExternalSystemCommand(int ExternalSystemId, string Name, string EndpointUrl, string AuthType, string? AuthConfiguration);
|
||||
public record DeleteExternalSystemCommand(int ExternalSystemId);
|
||||
|
||||
// External System Methods
|
||||
public record ListExternalSystemMethodsCommand(int ExternalSystemId);
|
||||
public record GetExternalSystemMethodCommand(int MethodId);
|
||||
public record CreateExternalSystemMethodCommand(int ExternalSystemId, string Name, string HttpMethod, string Path, string? ParameterDefinitions = null, string? ReturnDefinition = null);
|
||||
public record UpdateExternalSystemMethodCommand(int MethodId, string? Name = null, string? HttpMethod = null, string? Path = null, string? ParameterDefinitions = null, string? ReturnDefinition = null);
|
||||
public record DeleteExternalSystemMethodCommand(int MethodId);
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record GetHealthSummaryCommand;
|
||||
public record GetSiteHealthCommand(string SiteIdentifier);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListApiMethodsCommand;
|
||||
public record GetApiMethodCommand(int ApiMethodId);
|
||||
public record CreateApiMethodCommand(string Name, string Script, int TimeoutSeconds, string? ParameterDefinitions, string? ReturnDefinition);
|
||||
public record UpdateApiMethodCommand(int ApiMethodId, string Script, int TimeoutSeconds, string? ParameterDefinitions, string? ReturnDefinition);
|
||||
public record DeleteApiMethodCommand(int ApiMethodId);
|
||||
@@ -0,0 +1,38 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListInstancesCommand(int? SiteId = null, int? TemplateId = null, string? SearchTerm = null);
|
||||
public record GetInstanceCommand(int InstanceId);
|
||||
public record CreateInstanceCommand(string UniqueName, int TemplateId, int SiteId, int? AreaId = null);
|
||||
public record MgmtDeployInstanceCommand(int InstanceId);
|
||||
public record MgmtEnableInstanceCommand(int InstanceId);
|
||||
public record MgmtDisableInstanceCommand(int InstanceId);
|
||||
public record MgmtDeleteInstanceCommand(int InstanceId);
|
||||
/// <summary>
|
||||
/// A single attribute-to-data-connection binding carried by
|
||||
/// <see cref="SetConnectionBindingsCommand"/>. This is a named record (not a
|
||||
/// <c>ValueTuple</c>) so it serializes with stable, named JSON properties and can
|
||||
/// evolve additively per REQ-COM-5a.
|
||||
/// </summary>
|
||||
public record ConnectionBinding(string AttributeName, int DataConnectionId);
|
||||
|
||||
public record SetConnectionBindingsCommand(int InstanceId, IReadOnlyList<ConnectionBinding> Bindings);
|
||||
public record SetInstanceOverridesCommand(int InstanceId, IReadOnlyDictionary<string, string?> Overrides);
|
||||
public record SetInstanceAreaCommand(int InstanceId, int? AreaId);
|
||||
|
||||
/// <summary>
|
||||
/// Sets (or upserts) a per-instance alarm override. For HiLo trigger types the
|
||||
/// <c>TriggerConfigurationOverride</c> JSON is merged setpoint-by-setpoint with
|
||||
/// the inherited config; for binary trigger types it replaces the whole config.
|
||||
/// Either field is optional — pass null to leave it unchanged.
|
||||
/// </summary>
|
||||
public record SetInstanceAlarmOverrideCommand(
|
||||
int InstanceId,
|
||||
string AlarmCanonicalName,
|
||||
string? TriggerConfigurationOverride,
|
||||
int? PriorityLevelOverride);
|
||||
|
||||
public record DeleteInstanceAlarmOverrideCommand(
|
||||
int InstanceId,
|
||||
string AlarmCanonicalName);
|
||||
|
||||
public record ListInstanceAlarmOverridesCommand(int InstanceId);
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Frozen;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
/// <summary>
|
||||
/// Bidirectional name registry for management command records. The registry contains
|
||||
/// exactly the non-abstract <c>*Command</c> types declared in the
|
||||
/// <c>ZB.MOM.WW.ScadaBridge.Commons.Messages.Management</c> namespace; these are the commands that
|
||||
/// travel over the HTTP / ClusterClient management boundary.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="Resolve"/> and <see cref="GetCommandName"/> are symmetric:
|
||||
/// <c>Resolve(GetCommandName(t))</c> returns <c>t</c> for every type
|
||||
/// <see cref="GetCommandName"/> accepts. <see cref="GetCommandName"/> rejects any type
|
||||
/// the registry does not contain rather than computing an unresolvable name.
|
||||
/// </remarks>
|
||||
public static class ManagementCommandRegistry
|
||||
{
|
||||
private static readonly FrozenDictionary<string, Type> Commands = BuildRegistry();
|
||||
|
||||
/// <summary>
|
||||
/// Names keyed by command type, for the reverse lookup. Keeps
|
||||
/// <see cref="GetCommandName"/> in lock-step with the forward registry.
|
||||
/// </summary>
|
||||
private static readonly FrozenDictionary<Type, string> NamesByType =
|
||||
Commands.ToFrozenDictionary(kv => kv.Value, kv => kv.Key);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a management command wire name to its CLR type, or null if not registered.
|
||||
/// </summary>
|
||||
/// <param name="commandName">The wire name of the management command (without the "Command" suffix).</param>
|
||||
public static Type? Resolve(string commandName)
|
||||
{
|
||||
return Commands.GetValueOrDefault(commandName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the registered wire name for a management command type.
|
||||
/// </summary>
|
||||
/// <param name="commandType">The CLR type of the management command to look up.</param>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// Thrown when <paramref name="commandType"/> is not a registered management
|
||||
/// command — i.e. not a non-abstract <c>*Command</c> type in the
|
||||
/// <c>ZB.MOM.WW.ScadaBridge.Commons.Messages.Management</c> namespace. This keeps the method
|
||||
/// symmetric with <see cref="Resolve"/>: it never yields a name that
|
||||
/// <see cref="Resolve"/> cannot turn back into the same type.
|
||||
/// </exception>
|
||||
public static string GetCommandName(Type commandType)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(commandType);
|
||||
|
||||
if (NamesByType.TryGetValue(commandType, out var name))
|
||||
return name;
|
||||
|
||||
throw new ArgumentException(
|
||||
$"'{commandType.FullName}' is not a registered management command. " +
|
||||
$"Management commands must be non-abstract '*Command' records declared in " +
|
||||
$"the '{typeof(ManagementEnvelope).Namespace}' namespace.",
|
||||
nameof(commandType));
|
||||
}
|
||||
|
||||
private static FrozenDictionary<string, Type> BuildRegistry()
|
||||
{
|
||||
var ns = typeof(ManagementEnvelope).Namespace!;
|
||||
var assembly = typeof(ManagementEnvelope).Assembly;
|
||||
|
||||
return assembly.GetTypes()
|
||||
.Where(t => t.Namespace == ns
|
||||
&& t.Name.EndsWith("Command", StringComparison.Ordinal)
|
||||
&& !t.IsAbstract)
|
||||
.ToFrozenDictionary(
|
||||
t => t.Name[..^"Command".Length],
|
||||
t => t,
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record AuthenticatedUser(
|
||||
string Username, string DisplayName,
|
||||
string[] Roles, string[] PermittedSiteIds);
|
||||
|
||||
public record ManagementEnvelope(AuthenticatedUser User, object Command, string CorrelationId);
|
||||
|
||||
public record ManagementSuccess(string CorrelationId, string JsonData);
|
||||
public record ManagementError(string CorrelationId, string Error, string ErrorCode);
|
||||
public record ManagementUnauthorized(string CorrelationId, string Message);
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListNotificationListsCommand;
|
||||
public record GetNotificationListCommand(int NotificationListId);
|
||||
public record CreateNotificationListCommand(string Name, IReadOnlyList<string> RecipientEmails);
|
||||
public record UpdateNotificationListCommand(int NotificationListId, string Name, IReadOnlyList<string> RecipientEmails);
|
||||
public record DeleteNotificationListCommand(int NotificationListId);
|
||||
public record ListSmtpConfigsCommand;
|
||||
public record UpdateSmtpConfigCommand(int SmtpConfigId, string Server, int Port, string AuthMode, string FromAddress, string? TlsMode = null, string? Credentials = null);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record QueryEventLogsCommand(string SiteIdentifier, string? EventType = null, string? Severity = null, string? Keyword = null, DateTimeOffset? From = null, DateTimeOffset? To = null, int Page = 1, int PageSize = 50, string? InstanceName = null);
|
||||
public record QueryParkedMessagesCommand(string SiteIdentifier, int Page = 1, int PageSize = 50);
|
||||
public record RetryParkedMessageCommand(string SiteIdentifier, string MessageId);
|
||||
public record DiscardParkedMessageCommand(string SiteIdentifier, string MessageId);
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListApiKeysCommand;
|
||||
public record CreateApiKeyCommand(string Name);
|
||||
public record DeleteApiKeyCommand(int ApiKeyId);
|
||||
public record ListRoleMappingsCommand;
|
||||
public record CreateRoleMappingCommand(string LdapGroupName, string Role);
|
||||
public record UpdateRoleMappingCommand(int MappingId, string LdapGroupName, string Role);
|
||||
public record DeleteRoleMappingCommand(int MappingId);
|
||||
public record UpdateApiKeyCommand(int ApiKeyId, bool IsEnabled);
|
||||
public record ListScopeRulesCommand(int MappingId);
|
||||
public record AddScopeRuleCommand(int MappingId, int SiteId);
|
||||
public record DeleteScopeRuleCommand(int ScopeRuleId);
|
||||
public record ResolveRolesCommand(IReadOnlyList<string> LdapGroups);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListSharedScriptsCommand;
|
||||
public record GetSharedScriptCommand(int SharedScriptId);
|
||||
public record CreateSharedScriptCommand(string Name, string Code, string? ParameterDefinitions, string? ReturnDefinition);
|
||||
public record UpdateSharedScriptCommand(int SharedScriptId, string Name, string Code, string? ParameterDefinitions, string? ReturnDefinition);
|
||||
public record DeleteSharedScriptCommand(int SharedScriptId);
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListSitesCommand;
|
||||
public record GetSiteCommand(int SiteId);
|
||||
public record CreateSiteCommand(string Name, string SiteIdentifier, string? Description, string? NodeAAddress = null, string? NodeBAddress = null, string? GrpcNodeAAddress = null, string? GrpcNodeBAddress = null);
|
||||
public record UpdateSiteCommand(int SiteId, string Name, string? Description, string? NodeAAddress = null, string? NodeBAddress = null, string? GrpcNodeAAddress = null, string? GrpcNodeBAddress = null);
|
||||
public record DeleteSiteCommand(int SiteId);
|
||||
public record ListAreasCommand(int SiteId);
|
||||
public record CreateAreaCommand(int SiteId, string Name, int? ParentAreaId);
|
||||
public record DeleteAreaCommand(int AreaId);
|
||||
public record UpdateAreaCommand(int AreaId, string Name);
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListTemplatesCommand;
|
||||
public record GetTemplateCommand(int TemplateId);
|
||||
public record CreateTemplateCommand(string Name, string? Description, int? ParentTemplateId);
|
||||
public record UpdateTemplateCommand(int TemplateId, string Name, string? Description, int? ParentTemplateId);
|
||||
public record DeleteTemplateCommand(int TemplateId);
|
||||
public record ValidateTemplateCommand(int TemplateId);
|
||||
|
||||
// Template member operations
|
||||
public record AddTemplateAttributeCommand(int TemplateId, string Name, string DataType, string? Value, string? Description, string? DataSourceReference, bool IsLocked);
|
||||
public record UpdateTemplateAttributeCommand(int AttributeId, string Name, string DataType, string? Value, string? Description, string? DataSourceReference, bool IsLocked);
|
||||
public record DeleteTemplateAttributeCommand(int AttributeId);
|
||||
public record AddTemplateAlarmCommand(int TemplateId, string Name, string TriggerType, int PriorityLevel, string? Description, string? TriggerConfiguration, bool IsLocked);
|
||||
public record UpdateTemplateAlarmCommand(int AlarmId, string Name, string TriggerType, int PriorityLevel, string? Description, string? TriggerConfiguration, bool IsLocked);
|
||||
public record DeleteTemplateAlarmCommand(int AlarmId);
|
||||
public record AddTemplateScriptCommand(int TemplateId, string Name, string Code, string? TriggerType, string? TriggerConfiguration, bool IsLocked, string? ParameterDefinitions = null, string? ReturnDefinition = null);
|
||||
public record UpdateTemplateScriptCommand(int ScriptId, string Name, string Code, string? TriggerType, string? TriggerConfiguration, bool IsLocked, string? ParameterDefinitions = null, string? ReturnDefinition = null);
|
||||
public record DeleteTemplateScriptCommand(int ScriptId);
|
||||
public record AddTemplateCompositionCommand(int TemplateId, string InstanceName, int ComposedTemplateId);
|
||||
public record DeleteTemplateCompositionCommand(int CompositionId);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
public record ListTemplateFoldersCommand;
|
||||
public record CreateTemplateFolderCommand(string Name, int? ParentFolderId);
|
||||
public record RenameTemplateFolderCommand(int FolderId, string NewName);
|
||||
public record MoveTemplateFolderCommand(int FolderId, int? NewParentFolderId);
|
||||
public record DeleteTemplateFolderCommand(int FolderId);
|
||||
public record MoveTemplateToFolderCommand(int TemplateId, int? NewFolderId);
|
||||
@@ -0,0 +1,62 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Transport;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;
|
||||
|
||||
/// <summary>
|
||||
/// Exports a bundle. Names rather than IDs in the selection so test scripts can
|
||||
/// be written without an ID lookup step. <c>All=true</c> overrides the per-type
|
||||
/// name lists and exports every entity of every supported type.
|
||||
/// </summary>
|
||||
public sealed record ExportBundleCommand(
|
||||
bool All,
|
||||
IReadOnlyList<string>? TemplateNames,
|
||||
IReadOnlyList<string>? SharedScriptNames,
|
||||
IReadOnlyList<string>? ExternalSystemNames,
|
||||
IReadOnlyList<string>? DatabaseConnectionNames,
|
||||
IReadOnlyList<string>? NotificationListNames,
|
||||
IReadOnlyList<string>? SmtpConfigurationNames,
|
||||
IReadOnlyList<string>? ApiKeyNames,
|
||||
IReadOnlyList<string>? ApiMethodNames,
|
||||
bool IncludeDependencies,
|
||||
string? Passphrase,
|
||||
string SourceEnvironment);
|
||||
|
||||
/// <summary>
|
||||
/// Bundle body returned as base64-encoded ZIP. <see cref="ByteCount"/> is the
|
||||
/// pre-encoded size for sanity checks against the configured bundle cap.
|
||||
/// </summary>
|
||||
public sealed record ExportBundleResult(
|
||||
string Base64Bundle,
|
||||
int ByteCount);
|
||||
|
||||
/// <summary>
|
||||
/// Loads a bundle and returns its preview without applying anything. Useful
|
||||
/// for tests that want to assert on the diff shape before committing.
|
||||
/// </summary>
|
||||
public sealed record PreviewBundleCommand(
|
||||
string Base64Bundle,
|
||||
string? Passphrase);
|
||||
|
||||
public sealed record PreviewBundleResult(
|
||||
IReadOnlyList<ImportPreviewItem> Items,
|
||||
int AddCount,
|
||||
int ModifiedCount,
|
||||
int IdenticalCount,
|
||||
int BlockerCount);
|
||||
|
||||
/// <summary>
|
||||
/// Loads, previews, and applies a bundle in a single call. The diff is built
|
||||
/// internally; every <see cref="ConflictKind.Modified"/> row is resolved with
|
||||
/// <see cref="DefaultConflictPolicy"/>, every <see cref="ConflictKind.New"/>
|
||||
/// row gets <see cref="ResolutionAction.Add"/>, every
|
||||
/// <see cref="ConflictKind.Identical"/> row gets <see cref="ResolutionAction.Skip"/>,
|
||||
/// and any <see cref="ConflictKind.Blocker"/> row fails the call.
|
||||
/// <para>
|
||||
/// Valid <see cref="DefaultConflictPolicy"/> values: <c>"skip"</c>,
|
||||
/// <c>"overwrite"</c>, <c>"rename"</c>. Rename mints a unique suffix per row.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public sealed record ImportBundleCommand(
|
||||
string Base64Bundle,
|
||||
string? Passphrase,
|
||||
string DefaultConflictPolicy);
|
||||
@@ -0,0 +1,83 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Notification;
|
||||
|
||||
/// <summary>
|
||||
/// Site -> Central: submit a notification for central delivery.
|
||||
/// Fire-and-forget with ack; the site retries until a <see cref="NotificationSubmitAck"/> is received.
|
||||
/// </summary>
|
||||
/// <param name="OriginExecutionId">
|
||||
/// The originating script execution's <c>ExecutionId</c> (Audit Log #23). Stamped at
|
||||
/// <c>Notify.Send</c> time and carried, inside the serialized payload, through the site
|
||||
/// store-and-forward buffer so the central dispatcher can echo it onto the
|
||||
/// <c>NotifyDeliver</c> audit rows. Additive trailing member — null for messages built
|
||||
/// before the field existed, or for notifications raised outside a script execution.
|
||||
/// </param>
|
||||
/// <param name="OriginParentExecutionId">
|
||||
/// The originating routed script execution's <c>ParentExecutionId</c> (Audit Log #23).
|
||||
/// Stamped at <c>Notify.Send</c> time and carried, inside the serialized payload, through
|
||||
/// the site store-and-forward buffer so the central dispatcher can echo it onto the
|
||||
/// <c>NotifyDeliver</c> audit rows. Additive trailing member — null for messages built
|
||||
/// before the field existed, or for non-routed runs.
|
||||
/// </param>
|
||||
/// <param name="SourceNode">
|
||||
/// The cluster node on which the notification was emitted — `node-a` / `node-b` for site
|
||||
/// submissions, `central-a` / `central-b` for central-originated rows. Stamped by the
|
||||
/// emitting node from <c>INodeIdentityProvider</c> and carried, inside the serialized
|
||||
/// payload, through the site store-and-forward buffer so the central dispatcher can
|
||||
/// persist it on the <c>Notifications</c> row and echo it onto the <c>NotifyDeliver</c>
|
||||
/// audit rows. Additive trailing member — null for messages built before the field
|
||||
/// existed.
|
||||
/// </param>
|
||||
public record NotificationSubmit(
|
||||
string NotificationId,
|
||||
string ListName,
|
||||
string Subject,
|
||||
string Body,
|
||||
string SourceSiteId,
|
||||
string? SourceInstanceId,
|
||||
string? SourceScript,
|
||||
DateTimeOffset SiteEnqueuedAt,
|
||||
Guid? OriginExecutionId = null,
|
||||
Guid? OriginParentExecutionId = null,
|
||||
string? SourceNode = null);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Site: ack sent after the notification row is persisted.
|
||||
/// Idempotent — safe to re-send for the same <see cref="NotificationId"/>.
|
||||
/// </summary>
|
||||
public record NotificationSubmitAck(
|
||||
string NotificationId,
|
||||
bool Accepted,
|
||||
string? Error);
|
||||
|
||||
/// <summary>
|
||||
/// Site -> Central: query the central delivery status for a <see cref="NotificationId"/>.
|
||||
/// </summary>
|
||||
public record NotificationStatusQuery(
|
||||
string CorrelationId,
|
||||
string NotificationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Site: response carrying the current delivery status for a queried notification.
|
||||
/// </summary>
|
||||
public record NotificationStatusResponse(
|
||||
string CorrelationId,
|
||||
bool Found,
|
||||
string Status,
|
||||
int RetryCount,
|
||||
string? LastError,
|
||||
DateTimeOffset? DeliveredAt);
|
||||
|
||||
/// <summary>
|
||||
/// Notification Outbox: the delivery status of a notification, as returned to a
|
||||
/// script by <c>Notify.Status(id)</c>.
|
||||
///
|
||||
/// <see cref="Status"/> is either a central status (<c>Pending</c>, <c>Retrying</c>,
|
||||
/// <c>Delivered</c>, <c>Parked</c>, <c>Discarded</c>), the site-local <c>Forwarding</c>
|
||||
/// state (the notification is still buffered at the site and has not yet been
|
||||
/// forwarded/acked), or <c>Unknown</c> (no central row and not buffered locally).
|
||||
/// </summary>
|
||||
public record NotificationDeliveryStatus(
|
||||
string Status,
|
||||
int RetryCount,
|
||||
string? LastError,
|
||||
DateTimeOffset? DeliveredAt);
|
||||
@@ -0,0 +1,161 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Notifications;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Notification;
|
||||
|
||||
/// <summary>
|
||||
/// Outbox UI -> Central: paginated, filtered query over the notification outbox.
|
||||
/// All filter fields are optional; <see cref="StuckOnly"/> restricts results to stuck notifications.
|
||||
/// </summary>
|
||||
public record NotificationOutboxQueryRequest(
|
||||
string CorrelationId,
|
||||
string? StatusFilter,
|
||||
string? TypeFilter,
|
||||
string? SourceSiteFilter,
|
||||
string? ListNameFilter,
|
||||
bool StuckOnly,
|
||||
string? SubjectKeyword,
|
||||
DateTimeOffset? From,
|
||||
DateTimeOffset? To,
|
||||
int PageNumber,
|
||||
int PageSize,
|
||||
string? SourceNodeFilter = null);
|
||||
|
||||
/// <summary>
|
||||
/// A single notification row summarised for outbox UI display.
|
||||
/// </summary>
|
||||
public record NotificationSummary(
|
||||
string NotificationId,
|
||||
string Type,
|
||||
string ListName,
|
||||
string Subject,
|
||||
string Status,
|
||||
int RetryCount,
|
||||
string? LastError,
|
||||
string SourceSiteId,
|
||||
string? SourceInstanceId,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset? DeliveredAt,
|
||||
bool IsStuck,
|
||||
string? SourceNode = null);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Outbox UI: paginated response for a <see cref="NotificationOutboxQueryRequest"/>.
|
||||
/// </summary>
|
||||
public record NotificationOutboxQueryResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
IReadOnlyList<NotificationSummary> Notifications,
|
||||
int TotalCount);
|
||||
|
||||
/// <summary>
|
||||
/// Outbox UI -> Central: request to immediately retry delivery of a notification.
|
||||
/// </summary>
|
||||
public record RetryNotificationRequest(
|
||||
string CorrelationId,
|
||||
string NotificationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Outbox UI: result of a <see cref="RetryNotificationRequest"/>.
|
||||
/// </summary>
|
||||
public record RetryNotificationResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Outbox UI -> Central: request to discard (cancel) a pending or stuck notification.
|
||||
/// </summary>
|
||||
public record DiscardNotificationRequest(
|
||||
string CorrelationId,
|
||||
string NotificationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Outbox UI: result of a <see cref="DiscardNotificationRequest"/>.
|
||||
/// </summary>
|
||||
public record DiscardNotificationResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Outbox UI -> Central: request for the full detail of a single notification
|
||||
/// (including Body and resolved recipients), for the report detail modal.
|
||||
/// </summary>
|
||||
public record NotificationDetailRequest(
|
||||
string CorrelationId,
|
||||
string NotificationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Outbox UI: full detail for one notification. On a repository fault or
|
||||
/// missing row, Success is false / Detail is null and ErrorMessage carries the cause.
|
||||
/// </summary>
|
||||
public record NotificationDetailResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
NotificationDetail? Detail);
|
||||
|
||||
/// <summary>
|
||||
/// Full notification detail for the report detail modal — everything in the grid's
|
||||
/// NotificationSummary plus Body, ResolvedTargets (recipients), TypeData, SourceScript,
|
||||
/// and the additional lifecycle timestamps.
|
||||
/// </summary>
|
||||
public record NotificationDetail(
|
||||
string NotificationId,
|
||||
string Type,
|
||||
string ListName,
|
||||
string Subject,
|
||||
string Body,
|
||||
string Status,
|
||||
int RetryCount,
|
||||
string? LastError,
|
||||
string? ResolvedTargets,
|
||||
string? TypeData,
|
||||
string SourceSiteId,
|
||||
string? SourceInstanceId,
|
||||
string? SourceScript,
|
||||
DateTimeOffset SiteEnqueuedAt,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset? LastAttemptAt,
|
||||
DateTimeOffset? NextAttemptAt,
|
||||
DateTimeOffset? DeliveredAt,
|
||||
string? SourceNode = null);
|
||||
|
||||
/// <summary>
|
||||
/// Outbox UI -> Central: request for the notification outbox KPI summary.
|
||||
/// </summary>
|
||||
public record NotificationKpiRequest(
|
||||
string CorrelationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Outbox UI: KPI summary for the notification outbox dashboard.
|
||||
/// On a repository fault <see cref="Success"/> is <c>false</c>, <see cref="ErrorMessage"/>
|
||||
/// carries the cause, and the KPI fields are zeroed/<c>null</c>.
|
||||
/// </summary>
|
||||
public record NotificationKpiResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
int QueueDepth,
|
||||
int StuckCount,
|
||||
int ParkedCount,
|
||||
int DeliveredLastInterval,
|
||||
TimeSpan? OldestPendingAge);
|
||||
|
||||
/// <summary>
|
||||
/// Outbox UI -> Central: request for the per-source-site notification outbox KPI breakdown.
|
||||
/// </summary>
|
||||
public record PerSiteNotificationKpiRequest(
|
||||
string CorrelationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central -> Outbox UI: per-site KPI breakdown for the Notification KPIs page.
|
||||
/// On a repository fault <see cref="Success"/> is <c>false</c>, <see cref="ErrorMessage"/>
|
||||
/// carries the cause, and <see cref="Sites"/> is empty.
|
||||
/// </summary>
|
||||
public record PerSiteNotificationKpiResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
IReadOnlyList<SiteNotificationKpiSnapshot> Sites);
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// Request to query site event logs from central.
|
||||
/// Supports filtering by event type, severity, instance, time range, and keyword search.
|
||||
/// Uses keyset pagination via continuation token (last event ID).
|
||||
/// </summary>
|
||||
public record EventLogQueryRequest(
|
||||
string CorrelationId,
|
||||
string SiteId,
|
||||
DateTimeOffset? From,
|
||||
DateTimeOffset? To,
|
||||
string? EventType,
|
||||
string? Severity,
|
||||
string? InstanceId,
|
||||
string? KeywordFilter,
|
||||
long? ContinuationToken,
|
||||
int PageSize,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// A single event log entry returned from a site query.
|
||||
/// </summary>
|
||||
public record EventLogEntry(
|
||||
long Id,
|
||||
DateTimeOffset Timestamp,
|
||||
string EventType,
|
||||
string Severity,
|
||||
string? InstanceId,
|
||||
string Source,
|
||||
string Message,
|
||||
string? Details);
|
||||
|
||||
/// <summary>
|
||||
/// Response containing paginated event log entries from a site.
|
||||
/// Uses keyset pagination: ContinuationToken is the last event ID in the result set.
|
||||
/// </summary>
|
||||
public record EventLogQueryResponse(
|
||||
string CorrelationId,
|
||||
string SiteId,
|
||||
IReadOnlyList<EventLogEntry> Entries,
|
||||
long? ContinuationToken,
|
||||
bool HasMore,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// Request to permanently discard a parked message at a site.
|
||||
/// </summary>
|
||||
public record ParkedMessageDiscardRequest(
|
||||
string CorrelationId,
|
||||
string SiteId,
|
||||
string MessageId,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Response from discarding a parked message.
|
||||
/// </summary>
|
||||
public record ParkedMessageDiscardResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage = null);
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// Request to query parked (permanently failed) store-and-forward messages at a site.
|
||||
/// </summary>
|
||||
public record ParkedMessageQueryRequest(
|
||||
string CorrelationId,
|
||||
string SiteId,
|
||||
int PageNumber,
|
||||
int PageSize,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,29 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// Response containing parked store-and-forward messages from a site.
|
||||
/// </summary>
|
||||
public record ParkedMessageEntry(
|
||||
string MessageId,
|
||||
string TargetSystem,
|
||||
string MethodName,
|
||||
string ErrorMessage,
|
||||
int AttemptCount,
|
||||
DateTimeOffset OriginalTimestamp,
|
||||
DateTimeOffset LastAttemptTimestamp,
|
||||
int MaxAttempts = 0,
|
||||
StoreAndForwardCategory Category = StoreAndForwardCategory.ExternalSystem,
|
||||
string? OriginInstance = null);
|
||||
|
||||
public record ParkedMessageQueryResponse(
|
||||
string CorrelationId,
|
||||
string SiteId,
|
||||
IReadOnlyList<ParkedMessageEntry> Messages,
|
||||
int TotalCount,
|
||||
int PageNumber,
|
||||
int PageSize,
|
||||
bool Success,
|
||||
string? ErrorMessage,
|
||||
DateTimeOffset Timestamp);
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// Request to retry a parked message at a site (move back to pending queue).
|
||||
/// </summary>
|
||||
public record ParkedMessageRetryRequest(
|
||||
string CorrelationId,
|
||||
string SiteId,
|
||||
string MessageId,
|
||||
DateTimeOffset Timestamp);
|
||||
|
||||
/// <summary>
|
||||
/// Response from retrying a parked message.
|
||||
/// </summary>
|
||||
public record ParkedMessageRetryResponse(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
string? ErrorMessage = null);
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.RemoteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// Central → site relay command: retry a parked cached operation
|
||||
/// (<c>ExternalSystem.CachedCall</c> / <c>Database.CachedWrite</c>) on the
|
||||
/// owning site's Store-and-Forward buffer. Sent over the command/control
|
||||
/// channel by <c>SiteCallAuditActor</c> when an operator clicks Retry on a
|
||||
/// <c>Parked</c> Site Call row in the Central UI.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The site is the source of truth for cached-call status — central never
|
||||
/// mutates the central <c>SiteCalls</c> mirror row directly. This command asks
|
||||
/// the site to reset its own parked row back to <c>Pending</c> so the S&F
|
||||
/// retry sweep attempts delivery again; the corrected state then flows back to
|
||||
/// central via the normal cached-call telemetry path.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The cached call's S&F buffer message id is the
|
||||
/// <see cref="TrackedOperationId"/> itself (the tracked id is supplied as the
|
||||
/// buffered row's id at enqueue time), so the site can resolve the parked row
|
||||
/// directly from <see cref="TrackedOperationId"/>. A retry on a row that is not
|
||||
/// actually <c>Parked</c> is a safe no-op at the site — the ack reports
|
||||
/// <c>Applied=false</c> rather than corrupting a non-parked row.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This is a plain record carrying only ids, so it lives in Commons (no
|
||||
/// <c>IActorRef</c> field). It mirrors <see cref="ParkedMessageRetryRequest"/>
|
||||
/// but keys on <see cref="TrackedOperationId"/> rather than the opaque S&F
|
||||
/// message-id string.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed record RetryParkedOperation(
|
||||
string CorrelationId,
|
||||
TrackedOperationId TrackedOperationId);
|
||||
|
||||
/// <summary>
|
||||
/// Central → site relay command: discard a parked cached operation on the
|
||||
/// owning site's Store-and-Forward buffer. Sent over the command/control
|
||||
/// channel by <c>SiteCallAuditActor</c> when an operator clicks Discard on a
|
||||
/// <c>Parked</c> Site Call row in the Central UI. See
|
||||
/// <see cref="RetryParkedOperation"/> for the source-of-truth and message-id
|
||||
/// rationale; Discard marks the operation terminally <c>Discarded</c> at the
|
||||
/// site by removing the parked S&F buffer row.
|
||||
/// </summary>
|
||||
public sealed record DiscardParkedOperation(
|
||||
string CorrelationId,
|
||||
TrackedOperationId TrackedOperationId);
|
||||
|
||||
/// <summary>
|
||||
/// Site → central ack for a <see cref="RetryParkedOperation"/> /
|
||||
/// <see cref="DiscardParkedOperation"/> relay command. The site replies this
|
||||
/// after applying (or safely no-op-ing) the action against its own
|
||||
/// Store-and-Forward buffer.
|
||||
/// </summary>
|
||||
/// <param name="CorrelationId">Correlation id of the originating relay command.</param>
|
||||
/// <param name="Applied">
|
||||
/// <c>true</c> when the parked operation was found and the action was applied;
|
||||
/// <c>false</c> when no parked row matched the <see cref="RetryParkedOperation.TrackedOperationId"/>
|
||||
/// (already delivered, discarded, never cached, or not in a <c>Parked</c>
|
||||
/// state). A <c>false</c> ack is a definitive "nothing to do" answer from the
|
||||
/// site — it is NOT a transport failure, so the relay must distinguish it from
|
||||
/// a site-unreachable timeout.
|
||||
/// </param>
|
||||
/// <param name="ErrorMessage">
|
||||
/// Populated only when the site could not apply the action (e.g. the parked
|
||||
/// message handler is not available, or the S&F store faulted); <c>null</c>
|
||||
/// on a clean <c>Applied=true</c>/<c>Applied=false</c> outcome.
|
||||
/// </param>
|
||||
public sealed record ParkedOperationActionAck(
|
||||
string CorrelationId,
|
||||
bool Applied,
|
||||
string? ErrorMessage = null);
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.ScriptExecution;
|
||||
|
||||
/// <param name="ParentExecutionId">
|
||||
/// Audit Log #23 (ParentExecutionId): the spawning execution's <c>ExecutionId</c>.
|
||||
/// For an inbound-API-routed call this is the inbound request's per-request
|
||||
/// execution id (carried in from <c>RouteToCallRequest.ParentExecutionId</c>);
|
||||
/// the routed script execution records it as its <c>ParentExecutionId</c> so a
|
||||
/// spawned execution points back at its spawner. Additive trailing member —
|
||||
/// null for normal (tag-change / timer-triggered) runs, nested <c>Script.Call</c>
|
||||
/// invocations, and any request built before the field existed.
|
||||
/// </param>
|
||||
public record ScriptCallRequest(
|
||||
string ScriptName,
|
||||
IReadOnlyDictionary<string, object?>? Parameters,
|
||||
int CurrentCallDepth,
|
||||
string CorrelationId,
|
||||
Guid? ParentExecutionId = null);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.ScriptExecution;
|
||||
|
||||
public record ScriptCallResult(
|
||||
string CorrelationId,
|
||||
bool Success,
|
||||
object? ReturnValue,
|
||||
string? ErrorMessage);
|
||||
@@ -0,0 +1,29 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Streaming;
|
||||
|
||||
public record AlarmStateChanged(
|
||||
string InstanceUniqueName,
|
||||
string AlarmName,
|
||||
AlarmState State,
|
||||
int Priority,
|
||||
DateTimeOffset Timestamp) : ISiteStreamEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Severity level when <see cref="State"/> is <see cref="AlarmState.Active"/>.
|
||||
/// Always <see cref="AlarmLevel.None"/> for binary trigger types
|
||||
/// (ValueMatch, RangeViolation, RateOfChange); set by the HiLo trigger
|
||||
/// type to one of Low/LowLow/High/HighHigh based on the crossed setpoint.
|
||||
/// Added as an init-property so existing positional constructors still
|
||||
/// work — message contract evolves additively.
|
||||
/// </summary>
|
||||
public AlarmLevel Level { get; init; } = AlarmLevel.None;
|
||||
|
||||
/// <summary>
|
||||
/// Optional per-band operator message (e.g., "Coolant critically low —
|
||||
/// shut down"). Set by HiLo triggers when the per-setpoint message is
|
||||
/// configured; otherwise empty. Notification routing and UI tooltips may
|
||||
/// surface this to operators.
|
||||
/// </summary>
|
||||
public string Message { get; init; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Streaming;
|
||||
|
||||
public record AttributeValueChanged(
|
||||
string InstanceUniqueName,
|
||||
string AttributePath,
|
||||
string AttributeName,
|
||||
object? Value,
|
||||
string Quality,
|
||||
DateTimeOffset Timestamp) : ISiteStreamEvent;
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Streaming;
|
||||
|
||||
/// <summary>
|
||||
/// Marker interface for events published to the site-wide stream
|
||||
/// (attribute value changes and alarm state changes).
|
||||
/// </summary>
|
||||
public interface ISiteStreamEvent
|
||||
{
|
||||
/// <summary>The unique name of the instance that produced this event.</summary>
|
||||
string InstanceUniqueName { get; }
|
||||
}
|
||||
Reference in New Issue
Block a user