Merge branch 'worktree-agent-a27e5c199270a6d63' into arch-review-remediation

This commit is contained in:
Joseph Doherty
2026-08-14 20:14:13 -04:00
4 changed files with 120 additions and 12 deletions
@@ -24,8 +24,10 @@ public interface ISiteCommandTransport
/// Routes <paramref name="envelope"/>'s message to its site. Any reply the site produces is
/// delivered to <paramref name="replyTo"/> — for an <c>Ask</c> that is the temporary ask actor
/// (completing the caller's task); for a <c>Tell</c>-with-sender (the debug bridge) that is the
/// originating actor. A message with no route (an unknown site) is warned and dropped so the
/// caller's <c>Ask</c> times out — central never buffers for an unreachable site.
/// originating actor. A message with no route (an unknown/unconfigured site) fails fast: a
/// <see cref="Status.Failure"/> is delivered to <paramref name="replyTo"/> immediately instead of
/// letting the caller's <c>Ask</c> burn its full timeout — central still never buffers for an
/// unreachable site.
/// </summary>
/// <param name="envelope">The site-addressed command envelope.</param>
/// <param name="replyTo">Where a reply (or a <see cref="Status.Failure"/>) is delivered.</param>
@@ -22,9 +22,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc;
/// <remarks>
/// <para>
/// <b>Per-call deadlines match today's Ask timeouts exactly</b> — see <see cref="ResolveDeadline"/>.
/// Behaviour is otherwise unchanged from the Akka path: an unknown/unconfigured site is warned and
/// dropped (the caller's Ask times out), and a transport fault surfaces to the caller as a
/// <see cref="Status.Failure"/>, which the S&amp;F/audit layers already treat as transient.
/// An unknown/unconfigured site now fails fast: it surfaces to the caller as a
/// <see cref="Status.Failure"/> immediately (WP1.6) instead of being warned-and-dropped to let the
/// caller's Ask burn its full timeout. A transport fault takes the same <see cref="Status.Failure"/>
/// path, which the S&amp;F/audit layers already treat as transient.
/// </para>
/// <para>
/// <b>Cross-node retry is the channel provider's job</b> and happens only on
@@ -79,13 +80,21 @@ public sealed class GrpcSiteTransport : ISiteCommandTransport
replyTo.Tell(reply, ActorRefs.NoSender);
}
}
catch (SiteChannelUnavailableException)
catch (SiteChannelUnavailableException ex)
{
// Parity with the removed Akka "no ClusterClient for site" path: warn and drop, so the caller's
// Ask times out. Central never buffers.
// WP1.6: a known-dead send (no configured channel for this site) used to warn-and-drop,
// leaving the caller's Ask to burn its full timeout for a failure we already know about.
// Fail fast instead — same Status.Failure completion path a transport fault takes below —
// so S&F/audit treat it as transient immediately rather than tens of seconds later.
// Central still never buffers for an unreachable site; only the completion timing changed.
_logger.LogWarning(
"No gRPC channel for site {SiteId}; dropping {Message} (caller's Ask will time out)",
"No gRPC channel for site {SiteId}; failing {Message} immediately instead of dropping it",
envelope.SiteId, envelope.Message.GetType().Name);
if (!fireAndForget && !replyTo.IsNobody())
{
replyTo.Tell(new Status.Failure(ex), ActorRefs.NoSender);
}
}
catch (Exception ex)
{
@@ -8,9 +8,11 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc;
/// <summary>
/// Raised when a site has no usable gRPC channel — an unknown site, or a site with neither
/// <c>GrpcNodeAAddress</c> nor <c>GrpcNodeBAddress</c> configured. The gRPC transport treats this
/// the way the removed Akka path treated "no ClusterClient for site": warn and drop, so the caller's Ask
/// times out (central never buffers).
/// <c>GrpcNodeAAddress</c> nor <c>GrpcNodeBAddress</c> configured. <see cref="GrpcSiteTransport"/>
/// treats this as a known-dead send: it fails the caller's <c>Ask</c> fast with an
/// <c>Akka.Actor.Status.Failure</c> wrapping this exception (WP1.6) instead of warning and dropping
/// the message, so the caller does not burn its full Ask timeout on a failure already known at send
/// time (central still never buffers).
/// </summary>
public sealed class SiteChannelUnavailableException(string siteId)
: Exception($"No gRPC channel is configured for site '{siteId}'.")