fix(management): invalidate ExternalDefinitionLookupCache on external-system / DB-connection edits (ScadaBridge#65)
ManagementActor now drops the central definition cache post-commit (via the existing AfterConfigurationCommit seam) after every external system, external-system method and database connection create/update/delete, so an edit takes effect on the editing node immediately instead of after DefinitionCacheTtl. ManagementService gains a project reference to ExternalSystemGateway. The other central node still converges within the TTL.
This commit is contained in:
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems;
|
||||
using ZB.MOM.WW.ScadaBridge.ExternalSystemGateway;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.InboundApi;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Scripts;
|
||||
@@ -2364,6 +2365,23 @@ public class ManagementActor : ReceiveActor
|
||||
HasAuthConfiguration = !string.IsNullOrEmpty(d.AuthConfiguration),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Drops this node's <see cref="ExternalDefinitionLookupCache"/> once an external-system /
|
||||
/// external-system-method / database-connection edit has committed, so the next inbound-method
|
||||
/// call on this node resolves the fresh definition rather than waiting out
|
||||
/// <c>DefinitionCacheTtl</c> (ScadaBridge#65). Queued post-commit: invalidating before the commit
|
||||
/// would let a concurrent lookup re-cache the pre-edit row. The cache is per-node, so the other
|
||||
/// central node still converges within <c>DefinitionCacheTtl</c>. A no-op when the cache is not
|
||||
/// registered (site roles, plain test hosts).
|
||||
/// </summary>
|
||||
private static Task InvalidateExternalDefinitionCacheAfterCommit(IServiceProvider sp)
|
||||
{
|
||||
var cache = sp.GetService<ExternalDefinitionLookupCache>();
|
||||
return cache is null
|
||||
? Task.CompletedTask
|
||||
: AfterConfigurationCommit(sp, () => { cache.InvalidateAll(); return Task.CompletedTask; });
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleListExternalSystems(IServiceProvider sp)
|
||||
{
|
||||
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
||||
@@ -2392,6 +2410,7 @@ public class ManagementActor : ReceiveActor
|
||||
await repo.AddExternalSystemAsync(def);
|
||||
await repo.SaveChangesAsync();
|
||||
var publicShape = ExternalSystemPublicShape(def);
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Create", "ExternalSystem", def.Id.ToString(), def.Name, publicShape);
|
||||
return publicShape;
|
||||
}
|
||||
@@ -2414,6 +2433,7 @@ public class ManagementActor : ReceiveActor
|
||||
await repo.UpdateExternalSystemAsync(def);
|
||||
await repo.SaveChangesAsync();
|
||||
var publicShape = ExternalSystemPublicShape(def);
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Update", "ExternalSystem", def.Id.ToString(), def.Name, publicShape);
|
||||
return publicShape;
|
||||
}
|
||||
@@ -2423,6 +2443,7 @@ public class ManagementActor : ReceiveActor
|
||||
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
||||
await repo.DeleteExternalSystemAsync(cmd.ExternalSystemId);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Delete", "ExternalSystem", cmd.ExternalSystemId.ToString(), cmd.ExternalSystemId.ToString(), null);
|
||||
return true;
|
||||
}
|
||||
@@ -2450,6 +2471,7 @@ public class ManagementActor : ReceiveActor
|
||||
};
|
||||
await repo.AddExternalSystemMethodAsync(method);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Create", "ExternalSystemMethod", method.Id.ToString(), method.Name, method);
|
||||
return method;
|
||||
}
|
||||
@@ -2466,6 +2488,7 @@ public class ManagementActor : ReceiveActor
|
||||
if (cmd.ReturnDefinition != null) method.ReturnDefinition = cmd.ReturnDefinition;
|
||||
await repo.UpdateExternalSystemMethodAsync(method);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Update", "ExternalSystemMethod", method.Id.ToString(), method.Name, method);
|
||||
return method;
|
||||
}
|
||||
@@ -2475,6 +2498,7 @@ public class ManagementActor : ReceiveActor
|
||||
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
||||
await repo.DeleteExternalSystemMethodAsync(cmd.MethodId);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Delete", "ExternalSystemMethod", cmd.MethodId.ToString(), cmd.MethodId.ToString(), null);
|
||||
return true;
|
||||
}
|
||||
@@ -3681,6 +3705,7 @@ public class ManagementActor : ReceiveActor
|
||||
if (cmd.RetryDelay is { } retryDelay) def.RetryDelay = retryDelay;
|
||||
await repo.AddDatabaseConnectionAsync(def);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Create", "DatabaseConnection", def.Id.ToString(), def.Name, new { def.Id, def.Name });
|
||||
return DatabaseConnectionPublicShape(def);
|
||||
}
|
||||
@@ -3699,6 +3724,7 @@ public class ManagementActor : ReceiveActor
|
||||
if (cmd.RetryDelay is { } retryDelay) def.RetryDelay = retryDelay;
|
||||
await repo.UpdateDatabaseConnectionAsync(def);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Update", "DatabaseConnection", def.Id.ToString(), def.Name, new { def.Id, def.Name });
|
||||
return DatabaseConnectionPublicShape(def);
|
||||
}
|
||||
@@ -3708,6 +3734,7 @@ public class ManagementActor : ReceiveActor
|
||||
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
||||
await repo.DeleteDatabaseConnectionAsync(cmd.DatabaseConnectionId);
|
||||
await repo.SaveChangesAsync();
|
||||
await InvalidateExternalDefinitionCacheAfterCommit(sp);
|
||||
await AuditAsync(sp, user, "Delete", "DatabaseConnection", cmd.DatabaseConnectionId.ToString(), cmd.DatabaseConnectionId.ToString(), null);
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
@@ -24,5 +24,6 @@
|
||||
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.Security/ZB.MOM.WW.ScadaBridge.Security.csproj" />
|
||||
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.HealthMonitoring/ZB.MOM.WW.ScadaBridge.HealthMonitoring.csproj" />
|
||||
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.InboundAPI/ZB.MOM.WW.ScadaBridge.InboundAPI.csproj" />
|
||||
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user