diff --git a/src/Components/Server/src/Circuits/CircuitHost.cs b/src/Components/Server/src/Circuits/CircuitHost.cs index ba684e1984cd..11dcdb3e5234 100644 --- a/src/Components/Server/src/Circuits/CircuitHost.cs +++ b/src/Components/Server/src/Circuits/CircuitHost.cs @@ -30,6 +30,7 @@ internal partial class CircuitHost : IAsyncDisposable private CircuitHandler[] _circuitHandlers; private bool _initialized; private bool _isFirstUpdate = true; + private bool _onConnectionDownFired; private bool _disposed; private long _startTime; private PersistedCircuitState _persistedCircuitState; @@ -279,6 +280,7 @@ private async Task OnCircuitOpenedAsync(CancellationToken cancellationToken) public async Task OnConnectionUpAsync(CancellationToken cancellationToken) { + _onConnectionDownFired = false; Log.ConnectionUp(_logger, CircuitId, Client.ConnectionId); _circuitMetrics?.OnConnectionUp(); @@ -309,6 +311,12 @@ public async Task OnConnectionUpAsync(CancellationToken cancellationToken) public async Task OnConnectionDownAsync(CancellationToken cancellationToken) { + if(_onConnectionDownFired) + { + return; + } + + _onConnectionDownFired = true; Log.ConnectionDown(_logger, CircuitId, Client.ConnectionId); _circuitMetrics?.OnConnectionDown(); diff --git a/src/Components/Server/src/Circuits/CircuitMetrics.cs b/src/Components/Server/src/Circuits/CircuitMetrics.cs index 9432c6d18678..2d7c84dea66a 100644 --- a/src/Components/Server/src/Circuits/CircuitMetrics.cs +++ b/src/Components/Server/src/Circuits/CircuitMetrics.cs @@ -70,11 +70,6 @@ public void OnCircuitDown(long startTimestamp, long currentTimestamp) _circuitActiveCounter.Add(-1); } - if (_circuitConnectedCounter.Enabled) - { - _circuitConnectedCounter.Add(-1); - } - if (_circuitDuration.Enabled) { var duration = Stopwatch.GetElapsedTime(startTimestamp, currentTimestamp); diff --git a/src/Components/Server/src/Circuits/CircuitRegistry.cs b/src/Components/Server/src/Circuits/CircuitRegistry.cs index 6b068e56eae1..c26ca6d27160 100644 --- a/src/Components/Server/src/Circuits/CircuitRegistry.cs +++ b/src/Components/Server/src/Circuits/CircuitRegistry.cs @@ -311,6 +311,7 @@ private async Task PauseAndDisposeCircuitHost(CircuitHost circuitHost, bool save { await _circuitPersistenceManager.PauseCircuitAsync(circuitHost, saveStateToClient); circuitHost.UnhandledException -= CircuitHost_UnhandledException; + circuitHost.Client.SetDisconnected(); await circuitHost.DisposeAsync(); } diff --git a/src/Components/Server/test/Circuits/CircuitMetricsTest.cs b/src/Components/Server/test/Circuits/CircuitMetricsTest.cs index 8394b01036dc..b1e3ae3c44a2 100644 --- a/src/Components/Server/test/Circuits/CircuitMetricsTest.cs +++ b/src/Components/Server/test/Circuits/CircuitMetricsTest.cs @@ -108,15 +108,11 @@ public async Task OnCircuitDown_UpdatesCountersAndRecordsDuration() // Assert var activeMeasurements = activeCircuitCounter.GetMeasurementSnapshot(); - var connectedMeasurements = connectedCircuitCounter.GetMeasurementSnapshot(); var durationMeasurements = circuitDurationCollector.GetMeasurementSnapshot(); Assert.Single(activeMeasurements); Assert.Equal(-1, activeMeasurements[0].Value); - Assert.Single(connectedMeasurements); - Assert.Equal(-1, connectedMeasurements[0].Value); - Assert.Single(durationMeasurements); Assert.True(durationMeasurements[0].Value > 0); } @@ -162,7 +158,10 @@ public void FullCircuitLifecycle_RecordsAllMetricsCorrectly() // 4. Connection re-established circuitMetrics.OnConnectionUp(); - // 5. Circuit closes + // 5. Connection drops + circuitMetrics.OnConnectionDown(); + + // 6. Circuit closes Thread.Sleep(10); // Add a small delay to ensure a measurable duration var endTime = Stopwatch.GetTimestamp(); circuitMetrics.OnCircuitDown(startTime, endTime);