merge: external-system retry policy end-to-end (register row 27) — MaxRetries/RetryDelay now travel artifact→gRPC→site schema→S&F enqueue, CLI --max-retries/--retry-delay-seconds, ArtifactDiff compares them

This commit is contained in:
Joseph Doherty
2026-08-15 17:56:21 -04:00
28 changed files with 1036 additions and 453 deletions
@@ -9,6 +9,7 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Transport;
using ZB.MOM.WW.ScadaBridge.Transport.Import;
using ZB.MOM.WW.ScadaBridge.Transport.Serialization;
using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems;
namespace ZB.MOM.WW.ScadaBridge.Transport.Tests.Import;
@@ -105,6 +106,56 @@ public sealed class ArtifactDiffTests
Assert.Null(item.FieldDiffJson);
}
// ============ Deferred-work row 27: ES retry policy in the diff ============
/// <summary>
/// The bundle has always CARRIED the external-system retry policy and
/// <c>BundleImporter</c> has always APPLIED it, but <c>CompareExternalSystem</c> never
/// compared it — so an import that silently changed a system's retry budget previewed as
/// "Identical". Now that the policy actually reaches sites, an unreviewed change to it is a
/// live behaviour change, so it must show up in the preview.
/// </summary>
[Fact]
public void ExternalSystem_ChangedRetryPolicy_IsReported()
{
var existing = new ExternalSystemDefinition("Mes", "https://mes", "ApiKey")
{
MaxRetries = 3,
RetryDelay = TimeSpan.FromSeconds(5),
};
var incoming = new ExternalSystemDto("Mes", "https://mes", "ApiKey",
MaxRetries: 9, RetryDelay: TimeSpan.FromSeconds(45), Methods: [], Secrets: null);
var item = _diff.CompareExternalSystem(incoming, existing, []);
Assert.Equal(ConflictKind.Modified, item.Kind);
var maxRetries = ChangeFor(item, "MaxRetries");
Assert.Equal("3", maxRetries.GetProperty("oldValue").GetString());
Assert.Equal("9", maxRetries.GetProperty("newValue").GetString());
var retryDelay = ChangeFor(item, "RetryDelay");
Assert.Equal(TimeSpan.FromSeconds(5).ToString(), retryDelay.GetProperty("oldValue").GetString());
Assert.Equal(TimeSpan.FromSeconds(45).ToString(), retryDelay.GetProperty("newValue").GetString());
}
/// <summary>An unchanged retry policy must not manufacture a spurious diff row.</summary>
[Fact]
public void ExternalSystem_UnchangedRetryPolicy_IsIdentical()
{
var existing = new ExternalSystemDefinition("Mes", "https://mes", "ApiKey")
{
MaxRetries = 3,
RetryDelay = TimeSpan.FromSeconds(5),
};
var incoming = new ExternalSystemDto("Mes", "https://mes", "ApiKey",
MaxRetries: 3, RetryDelay: TimeSpan.FromSeconds(5), Methods: [], Secrets: null);
var item = _diff.CompareExternalSystem(incoming, existing, []);
Assert.Equal(ConflictKind.Identical, item.Kind);
}
[Fact]
public void ApiMethod_ModifiedScript_EmitsStructuredLineDiff()
{