a04196d725
The driver-status and resilience stores had no removal path, so a deleted driver stayed on /hosts as a frozen row until restart. Both stores gain RetainOnly, which /hosts calls after each successful config load (never on a failed one). The stores and InProcessBroadcaster now raise their events one subscriber at a time, so a throwing handler cannot starve later subscribers or escape onto the bridge actor. The alert/script-log bridges publish inside their try, and the resilience bridge catches a store failure instead of restarting. Refs #745 Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
26 lines
1.2 KiB
C#
26 lines
1.2 KiB
C#
using Shouldly;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests;
|
|
|
|
/// <summary>
|
|
/// Reads an AdminUI source file for a source-scan pin. The repo has no bUnit, so Razor wiring that a
|
|
/// unit test cannot render is pinned by scanning the markup; it proves the wiring exists, not that it
|
|
/// renders correctly (the docker-dev live pass covers that).
|
|
/// </summary>
|
|
internal static class AdminUiSource
|
|
{
|
|
/// <summary>Reads a file under <c>src/Server/ZB.MOM.WW.OtOpcUa.AdminUI</c>.</summary>
|
|
/// <param name="relativeSegments">Path segments below the AdminUI project directory.</param>
|
|
/// <returns>The file text.</returns>
|
|
public static string Read(params string[] relativeSegments)
|
|
{
|
|
var dir = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (dir is not null && !File.Exists(Path.Combine(dir.FullName, "ZB.MOM.WW.OtOpcUa.slnx")))
|
|
dir = dir.Parent;
|
|
dir.ShouldNotBeNull("could not locate the repository root (no ZB.MOM.WW.OtOpcUa.slnx above the test binary)");
|
|
|
|
var parts = new[] { dir!.FullName, "src", "Server", "ZB.MOM.WW.OtOpcUa.AdminUI" }.Concat(relativeSegments).ToArray();
|
|
return File.ReadAllText(Path.Combine(parts));
|
|
}
|
|
}
|