refactor(driver-pages): address Phase 6/8 deep-review findings
v2-ci / build (push) Failing after 32s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
v2-ci / build (push) Failing after 32s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
- Topic-name drift fix: DriverHealthChanged.TopicName and DriverControlTopic.Name now live on the message contracts in Commons. AkkaDriverHealthPublisher, DriverStatusSignalRBridge, DriverHostActor, and AdminOperationsActor all delegate to the single constant so a rename can't silently desynchronise publisher and subscriber. - DriverStatusPanel._opResultClearTimer switched from System.Timers.Timer to System.Threading.Timer + awaited DisposeAsync. Prevents an in-flight 8s clear-callback from invoking StateHasChanged on a component whose hub has already been released. - PublishHealthSnapshot deduplicates against the last published (state, lastSuccess, lastError, errorCount) fingerprint. The 30s heartbeat no longer floods the SignalR layer with identical Healthy snapshots — newly-joined clients still warm up via the snapshot store on JoinDriver.
This commit is contained in:
+10
-11
@@ -157,7 +157,7 @@
|
||||
private bool _showRestartConfirm;
|
||||
private string? _opResultMessage;
|
||||
private bool _opResultOk;
|
||||
private System.Timers.Timer? _opResultClearTimer;
|
||||
private System.Threading.Timer? _opResultClearTimer;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
@@ -257,24 +257,23 @@
|
||||
{
|
||||
_opResultOk = ok;
|
||||
_opResultMessage = message;
|
||||
// Auto-clear the result chip after 8 s.
|
||||
// Auto-clear the result chip after 8 s. System.Threading.Timer is used (not
|
||||
// System.Timers.Timer) so DisposeAsync can drain any in-flight callback.
|
||||
_opResultClearTimer?.Dispose();
|
||||
_opResultClearTimer = new System.Timers.Timer(8_000) { AutoReset = false };
|
||||
_opResultClearTimer.Elapsed += async (_, _) =>
|
||||
_opResultClearTimer = new System.Threading.Timer(_ =>
|
||||
{
|
||||
_opResultMessage = null;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
};
|
||||
_opResultClearTimer.Start();
|
||||
InvokeAsync(StateHasChanged);
|
||||
}, null, TimeSpan.FromSeconds(8), Timeout.InfiniteTimeSpan);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
// Drain the timer first so an in-flight callback can't invoke StateHasChanged on
|
||||
// a component that's already releasing its hub. System.Threading.Timer implements
|
||||
// IAsyncDisposable in .NET 6+; the async dispose awaits any in-flight callback.
|
||||
// Drain BOTH timers first so an in-flight callback can't invoke StateHasChanged on
|
||||
// a component whose hub has already been released. System.Threading.Timer's async
|
||||
// dispose awaits any in-flight callback (.NET 6+).
|
||||
if (_timer is not null) await _timer.DisposeAsync();
|
||||
_opResultClearTimer?.Dispose();
|
||||
if (_opResultClearTimer is not null) await _opResultClearTimer.DisposeAsync();
|
||||
if (_hub is not null) await _hub.DisposeAsync();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user