refactor(deployment): move PendingUpdatesCache to DeploymentManager so the CLI shares it (ScadaBridge#91)
`health pending-updates` (#63) called IPendingUpdatesEvaluator.EvaluateAsync directly from ManagementActor because the cache lived in CentralUI, so every CLI call was a full uncached fleet flatten. IPendingUpdatesCache/PendingUpdatesCache now live in DeploymentManager.PendingUpdates and are registered by AddDeploymentManager; the SingleFlightMemo<T> primitive moves to Commons.Caching (public) so both CentralUI's KPI / alarm-summary caches and DeploymentManager can use it. HandleGetPendingUpdates reads the shared cache; the UI circuits and the CLI now share one memo per node. Tests: ManagementActor repeated-calls test (fails against the direct evaluator call: 2 evaluations instead of 1), AddDeploymentManager singleton-registration test; the cache and memo tests move with their types. (ScadaBridge#91) Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -1848,7 +1848,7 @@ public class ManagementActorTests : TestKit, IDisposable
|
||||
Assert.Equal(envelope.CorrelationId, response.CorrelationId);
|
||||
}
|
||||
|
||||
private void RegisterPendingUpdates()
|
||||
private ZB.MOM.WW.ScadaBridge.DeploymentManager.PendingUpdates.IPendingUpdatesEvaluator RegisterPendingUpdates()
|
||||
{
|
||||
var evaluator = Substitute.For<ZB.MOM.WW.ScadaBridge.DeploymentManager.PendingUpdates.IPendingUpdatesEvaluator>();
|
||||
evaluator.EvaluateAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(
|
||||
@@ -1859,6 +1859,35 @@ public class ManagementActorTests : TestKit, IDisposable
|
||||
new(2, "S2", "Site 2", ZB.MOM.WW.ScadaBridge.DeploymentManager.PendingUpdates.ArtifactDeploymentState.Current, null, 10, 6, 0),
|
||||
])));
|
||||
_services.AddScoped(_ => evaluator);
|
||||
|
||||
// The real process-wide cache the Host registers via AddDeploymentManager (Gitea #91).
|
||||
_services.AddSingleton(Microsoft.Extensions.Options.Options.Create(
|
||||
new ZB.MOM.WW.ScadaBridge.DeploymentManager.DeploymentManagerOptions()));
|
||||
_services.AddSingleton<ZB.MOM.WW.ScadaBridge.DeploymentManager.IDeploymentStatusNotifier>(
|
||||
new ZB.MOM.WW.ScadaBridge.DeploymentManager.DeploymentStatusNotifier(
|
||||
Microsoft.Extensions.Logging.Abstractions.NullLogger<ZB.MOM.WW.ScadaBridge.DeploymentManager.DeploymentStatusNotifier>.Instance));
|
||||
_services.AddSingleton<
|
||||
ZB.MOM.WW.ScadaBridge.DeploymentManager.PendingUpdates.IPendingUpdatesCache,
|
||||
ZB.MOM.WW.ScadaBridge.DeploymentManager.PendingUpdates.PendingUpdatesCache>();
|
||||
return evaluator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gitea #91: repeated CLI calls inside one cache TTL share the process-wide
|
||||
/// pending-updates memo instead of each running a full fleet flatten.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void GetPendingUpdates_RepeatedCalls_ShareOneFleetEvaluation()
|
||||
{
|
||||
var evaluator = RegisterPendingUpdates();
|
||||
var actor = CreateActor();
|
||||
|
||||
actor.Tell(Envelope(new GetPendingUpdatesCommand(), "Deployer"));
|
||||
ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
actor.Tell(Envelope(new GetPendingUpdatesCommand(), "Deployer"));
|
||||
ExpectMsg<ManagementSuccess>(TimeSpan.FromSeconds(5));
|
||||
|
||||
evaluator.Received(1).EvaluateAsync(Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
/// <summary>Gitea #63: a system-wide Deployer gets fleet totals.</summary>
|
||||
|
||||
Reference in New Issue
Block a user