fix(transport): script-artifact change publisher covers Add resolutions — delete-then-reimport no longer starves non-self-healing subscribers (plan R2-05 T5)
This commit is contained in:
+55
@@ -1397,6 +1397,61 @@ public sealed class BundleImporterApplyTests : IDisposable
|
||||
Assert.All(_artifactBus.Received, n => Assert.Equal("BundleImport", n.Source));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ApplyAsync_publishes_ScriptArtifactsChanged_for_Add_resolutions()
|
||||
{
|
||||
// ApiMethod imported as Add into a target where the name does not exist.
|
||||
// Delete-then-reimport-as-Add is the N3 edge: a node can still hold a
|
||||
// _knownBadMethods / compiled-handler entry under that very name, so Adds
|
||||
// must notify too (over-approximation is safe per the bus contract).
|
||||
await using (var scope = _provider.CreateAsyncScope())
|
||||
{
|
||||
var ctx = scope.ServiceProvider.GetRequiredService<ScadaBridgeDbContext>();
|
||||
ctx.ApiMethods.Add(new ApiMethod("DelmiaRecipeDownload", "return 1;") { TimeoutSeconds = 30 });
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
Guid sessionId;
|
||||
await using (var scope = _provider.CreateAsyncScope())
|
||||
{
|
||||
var exporter = scope.ServiceProvider.GetRequiredService<IBundleExporter>();
|
||||
var ctx = scope.ServiceProvider.GetRequiredService<ScadaBridgeDbContext>();
|
||||
var selection = new ExportSelection(
|
||||
TemplateIds: Array.Empty<int>(),
|
||||
SharedScriptIds: Array.Empty<int>(),
|
||||
ExternalSystemIds: Array.Empty<int>(),
|
||||
DatabaseConnectionIds: Array.Empty<int>(),
|
||||
NotificationListIds: Array.Empty<int>(),
|
||||
SmtpConfigurationIds: Array.Empty<int>(),
|
||||
ApiMethodIds: await ctx.ApiMethods.Select(m => m.Id).ToListAsync(),
|
||||
IncludeDependencies: false);
|
||||
var stream = await exporter.ExportAsync(selection, user: "alice", sourceEnvironment: "dev",
|
||||
passphrase: null, cancellationToken: CancellationToken.None);
|
||||
using var ms = new MemoryStream();
|
||||
await stream.CopyToAsync(ms);
|
||||
ms.Position = 0;
|
||||
|
||||
// Delete the target method so the resolution is a genuine Add.
|
||||
ctx.ApiMethods.RemoveRange(await ctx.ApiMethods.ToListAsync());
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
var importer = scope.ServiceProvider.GetRequiredService<IBundleImporter>();
|
||||
sessionId = (await importer.LoadAsync(ms, passphrase: null)).SessionId;
|
||||
}
|
||||
|
||||
await using (var scope = _provider.CreateAsyncScope())
|
||||
{
|
||||
var importer = scope.ServiceProvider.GetRequiredService<IBundleImporter>();
|
||||
await importer.ApplyAsync(sessionId,
|
||||
new List<ImportResolution> { new("ApiMethod", "DelmiaRecipeDownload", ResolutionAction.Add, null) },
|
||||
user: "bob");
|
||||
}
|
||||
|
||||
var notification = Assert.Single(_artifactBus.Received,
|
||||
n => n.ArtifactKind == ScriptArtifactKinds.ApiMethod);
|
||||
Assert.Contains("DelmiaRecipeDownload", notification.Names); // FAILS today: Adds are filtered out
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ApplyAsync_failed_apply_publishes_nothing()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user