fix(deploy): derive the apply-outcome timeout from central's apply deadline (105 s) and name a timeout reason distinctly (#601 review)

60 s labelled a slow-but-clean large rebuild degraded. The deadline moves to a
shared Commons DeployTimings constant that ConfigPublishCoordinator reads, and
the node's timeout is deadline - 15 s margin, so the held ack still lands in
time. A timed-out ack's reason now says the outcome was not reported in time,
distinct from a real sink failure.

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 17:54:09 -04:00
parent af02fce3c4
commit 0a821417ea
6 changed files with 67 additions and 13 deletions
@@ -0,0 +1,25 @@
namespace ZB.MOM.WW.OtOpcUa.Commons.Messages.Deploy;
/// <summary>
/// The deploy-path timing contract shared by central (<c>ConfigPublishCoordinator</c>) and the node
/// (<c>DriverHostActor</c>). One place, so the node's ack-hold timeout can never drift past the deadline
/// central times the deployment out on.
/// </summary>
public static class DeployTimings
{
/// <summary>How long central waits for every expected node's ack before sealing the deployment TimedOut
/// (<c>ConfigPublishCoordinator.DefaultApplyDeadline</c>).</summary>
public static readonly TimeSpan ApplyDeadline = TimeSpan.FromMinutes(2);
/// <summary>Gitea #601 — how far inside <see cref="ApplyDeadline"/> a node's held Applied ack is released
/// when the address-space outcome has not arrived, leaving room for transport latency.</summary>
public static readonly TimeSpan ApplyOutcomeSafetyMargin = TimeSpan.FromSeconds(15);
/// <summary>Gitea #601 — the node's default apply-outcome timeout: <see cref="ApplyDeadline"/> −
/// <see cref="ApplyOutcomeSafetyMargin"/> (105 s). Long enough that a slow-but-clean rebuild of a large
/// address space is not labelled degraded, short enough to ack before central gives up.</summary>
/// <remarks>The timer is armed after the artifact read and driver reconcile, so if those alone took
/// longer than the margin the ack can still land after the deadline — accepted: they are seconds in
/// practice, and lengthening the margin would label more slow-but-clean rebuilds degraded.</remarks>
public static TimeSpan ApplyOutcomeTimeout => ApplyDeadline - ApplyOutcomeSafetyMargin;
}