diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs
index f502e6a2..a7cdfa41 100644
--- a/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationService.cs
@@ -134,6 +134,27 @@ public class CommunicationService
envelope, _options.DeploymentTimeout, cancellationToken);
}
+ ///
+ /// Sends a small "refresh deployment" notify to a site (notify-and-fetch).
+ /// Replaces on the wire: the site fetches the
+ /// config over HTTP rather than receiving it inline. Reply is the existing
+ /// DeploymentStatusResponse, bounded by the deployment timeout.
+ ///
+ /// The target site identifier.
+ /// The refresh-deployment notify.
+ /// Cancellation token.
+ /// The deployment status response.
+ public async Task RefreshDeploymentAsync(
+ string siteId, RefreshDeploymentCommand command, CancellationToken cancellationToken = default)
+ {
+ _logger.LogInformation(
+ "Sending RefreshDeploymentCommand to site {SiteId}, instance={Instance}, deploymentId={DeploymentId}",
+ siteId, command.InstanceUniqueName, command.DeploymentId);
+ var envelope = new SiteEnvelope(siteId, command);
+ return await GetActor().Ask(
+ envelope, _options.DeploymentTimeout, cancellationToken);
+ }
+
///
/// DeploymentManager-006: queries a site for the currently-applied deployment
/// identity of a single instance. Used by the Deployment Manager before a
diff --git a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/CentralCommunicationActorTests.cs b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/CentralCommunicationActorTests.cs
index 90b557fe..a7dae8b0 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/CentralCommunicationActorTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/CentralCommunicationActorTests.cs
@@ -101,6 +101,25 @@ public class CentralCommunicationActorTests : TestKit
Assert.Equal("dep1", ((DeployInstanceCommand)msg.Message).DeploymentId);
}
+ [Fact]
+ public void ClusterClientRouting_RefreshDeploymentCommand_RoutesToSite()
+ {
+ var site = CreateSite("site1", "akka.tcp://scadabridge@host:8082");
+ var (actor, _, siteProbes) = CreateActorWithMockRepo(new[] { site });
+
+ Thread.Sleep(1000);
+
+ var command = new RefreshDeploymentCommand(
+ "dep1", "inst1", "rev1", "admin", DateTimeOffset.UtcNow,
+ "https://central:9000", "tok1");
+ actor.Tell(new SiteEnvelope("site1", command));
+
+ var msg = siteProbes["site1"].ExpectMsg();
+ Assert.Equal("/user/site-communication", msg.Path);
+ Assert.IsType(msg.Message);
+ Assert.Equal("dep1", ((RefreshDeploymentCommand)msg.Message).DeploymentId);
+ }
+
[Fact]
public void UnconfiguredSite_MessageIsDropped()
{