diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor
index 755beacc..64bb4dfc 100644
--- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor
+++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Deployment/Topology.razor
@@ -79,7 +79,7 @@
-
+
@@ -249,7 +249,9 @@
_ = _pollGate.RunAsync(
() => InvokeAsync(async () =>
{
- if (_disposed || !_liveUpdates) return;
+ // Also skip while a page action (e.g. Deploy all) is running: it has its own DI scope, but
+ // a refresh landing mid-action only churns the tree under the operator.
+ if (_disposed || !_liveUpdates || _actionInProgress) return;
// Staleness is deliberately OFF the live loop: it only changes when a
// template/instance is edited or redeployed, and recomputing it (a
// full re-flatten per deployed instance) every 15s is the page's
@@ -396,6 +398,8 @@
_branchLoading = true;
try
{
+ // Since #39 every permitted site's areas are pre-loaded each tick, so this guard is
+ // only reachable for a site created between ticks.
if (!_loadedSites.Contains(siteId))
{
_allAreas.AddRange(await TemplateEngineRepository.GetAreasBySiteIdAsync(siteId));
@@ -601,7 +605,7 @@
var loaded = _loadedPages.TryGetValue((node.SiteId, areaId), out var offset);
@if (!loaded)
{
-
+
}
else
{
@@ -1052,7 +1056,8 @@
{
var user = await GetCurrentUserAsync(inst.Id);
if (user is null) return;
- var result = await DeploymentService.DeployInstanceAsync(inst.Id, user);
+ await using var scope = ScopeFactory.CreateAsyncScope();
+ var result = await scope.ServiceProvider.GetRequiredService
- @Total instance@(Total == 1 ? "" : "s") + @Total instance@(Total == 1 ? "" : "s") in scope@(Disabled > 0 ? "" : ".") @if (Disabled > 0) { - (@Disabled disabled — will be skipped) + , @Disabled disabled (always skipped). } - . Instances already running the current configuration are skipped. + Unchanged instances are skipped unless Force is checked.