diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/FleetDiagnostics.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/FleetDiagnostics.razor
index 60d2c993..b2171f3a 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/FleetDiagnostics.razor
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/FleetDiagnostics.razor
@@ -115,7 +115,7 @@ else
- | Driver |
+ Driver instance |
Row id |
State |
Connected devices |
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
index 1e5be182..76c82ebf 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
@@ -2540,15 +2540,17 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers, IWithUnboundedS
}
///
- /// One child's diagnostics row. Device counts come from the driver's host statuses when it is an
- /// IHostConnectivityProbe (Running = connected; Stopped/Faulted = faulted; Unknown = neither);
- /// a single-host driver counts as one device, connected while it reports Healthy or Degraded and
- /// faulted while it reports Faulted. A child that has not published yet reports "Connecting" (or
- /// "Stubbed") with its spawn time as the last change.
+ /// One child's diagnostics row. Name carries the string driver-instance id — the identity every
+ /// other surface (/hosts, telemetry, the artifact) keys on — and DriverInstanceId the DB row Guid;
+ /// the wire record has no slot for the authored display name. Device counts come from the driver's host
+ /// statuses when it is an IHostConnectivityProbe (Running = connected; Stopped/Faulted = faulted;
+ /// Unknown = neither); a single-host driver counts as one device, connected while it reports Healthy or
+ /// Degraded and faulted while it reports Faulted. A child that has not published yet reports
+ /// "Connecting" (or "Stubbed") with its spawn time as the last change.
///
private static DriverInstanceDiagnostics ToDiagnostics(string driverInstanceId, ChildEntry entry, ChildHealthRecord? health)
{
- var name = string.IsNullOrEmpty(entry.Spec.Name) ? driverInstanceId : entry.Spec.Name;
+ var name = driverInstanceId;
if (entry.Stubbed)
return new DriverInstanceDiagnostics(entry.Spec.DriverInstanceRowId, name, "Stubbed", 0, 0, entry.SpawnedUtc);
if (health is null)
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorDiagnosticsTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorDiagnosticsTests.cs
index 4bd833cb..86ca424b 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorDiagnosticsTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorDiagnosticsTests.cs
@@ -11,7 +11,7 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers;
///
/// Review 02 U1: GetDiagnostics answered a placeholder — Guid.Empty, "Spawned", zero devices and
/// "now" for every child, in every behaviour — so the snapshot looked live and said nothing. It now carries
-/// each child's row id, authored name, last-published health state, device counts and last change time.
+/// each child's row id, instance id, last-published health state, device counts and last change time.
///
public sealed class DriverHostActorDiagnosticsTests : RuntimeActorTestBase
{
@@ -39,7 +39,7 @@ public sealed class DriverHostActorDiagnosticsTests : RuntimeActorTestBase
snapshot.RunningFromCache.ShouldBeFalse();
var driver = snapshot.Drivers.ShouldHaveSingleItem();
driver.DriverInstanceId.ShouldBe(rowId, "the real row id, not Guid.Empty");
- driver.Name.ShouldBe("Line1-Modbus", "the authored name, not the instance id");
+ driver.Name.ShouldBe(DriverId, "the string instance id every other surface keys on");
driver.State.ShouldBe("Healthy");
driver.ConnectedDevices.ShouldBe(1);
driver.FaultedDevices.ShouldBe(0);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverInstanceActorConcurrentWriteTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverInstanceActorConcurrentWriteTests.cs
index f44b21f3..b4bf5683 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverInstanceActorConcurrentWriteTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverInstanceActorConcurrentWriteTests.cs
@@ -96,7 +96,12 @@ public sealed class DriverInstanceActorConcurrentWriteTests : RuntimeActorTestBa
driver.ReleaseWrites();
var results = await Task.WhenAll(asks);
results.ShouldAllBe(r => r.Success);
- driver.Writes.Select(w => w.FullReference).ShouldBe(new[] { "tag-0", "tag-1", "tag-2", "tag-3" });
+ // Entry order: the first two slots went to the first two writes (in either order — they are
+ // concurrent), the queued pair entered only after a slot freed, in queue order.
+ var entered = driver.EnteredRefs;
+ entered.Count.ShouldBe(4);
+ entered.Take(2).ShouldBe(new[] { "tag-0", "tag-1" }, ignoreOrder: true);
+ entered.Skip(2).ShouldBe(new[] { "tag-2", "tag-3" });
}
[Fact]
@@ -129,6 +134,7 @@ public sealed class DriverInstanceActorConcurrentWriteTests : RuntimeActorTestBa
{
private readonly StubHandle _handle = new();
private readonly ConcurrentQueue _writes = new();
+ private readonly ConcurrentQueue _enteredRefs = new();
private TaskCompletionSource _release = new(TaskCreationOptions.RunContinuationsAsynchronously);
private int _entered;
private int _inside;
@@ -138,6 +144,7 @@ public sealed class DriverInstanceActorConcurrentWriteTests : RuntimeActorTestBa
public bool HoldWrites { get; init; }
public IReadOnlyList Writes => _writes.ToArray();
+ public IReadOnlyList EnteredRefs => _enteredRefs.ToArray();
public int WritesEntered => Volatile.Read(ref _entered);
public int MaxConcurrentWrites => Volatile.Read(ref _maxInside);
@@ -154,6 +161,7 @@ public sealed class DriverInstanceActorConcurrentWriteTests : RuntimeActorTestBa
public async Task> WriteAsync(IReadOnlyList writes, CancellationToken cancellationToken)
{
Interlocked.Increment(ref _entered);
+ foreach (var w in writes) _enteredRefs.Enqueue(w.FullReference);
var inside = Interlocked.Increment(ref _inside);
int seen;
while (inside > (seen = Volatile.Read(ref _maxInside)))