fix(historian): volatile _backoffIndex + read _evictedCount under lock (thread-safety)

This commit is contained in:
Joseph Doherty
2026-06-11 12:49:44 -04:00
parent 8012509584
commit c20d228384
@@ -71,7 +71,7 @@ public sealed class SqliteStoreAndForwardSink : IAlarmHistorianSink, IDisposable
private readonly SemaphoreSlim _drainGate = new(1, 1); private readonly SemaphoreSlim _drainGate = new(1, 1);
private Timer? _drainTimer; private Timer? _drainTimer;
private TimeSpan _tickInterval; private TimeSpan _tickInterval;
private int _backoffIndex; private volatile int _backoffIndex;
private bool _disposed; private bool _disposed;
// Core.AlarmHistorian-005: status fields written by the drain timer thread and // Core.AlarmHistorian-005: status fields written by the drain timer thread and
@@ -655,10 +655,11 @@ public sealed class SqliteStoreAndForwardSink : IAlarmHistorianSink, IDisposable
await cmd.ExecuteNonQueryAsync(ct).ConfigureAwait(false); await cmd.ExecuteNonQueryAsync(ct).ConfigureAwait(false);
} }
Interlocked.Add(ref _queuedRowCount, -toEvict); Interlocked.Add(ref _queuedRowCount, -toEvict);
lock (_statusLock) { _evictedCount += toEvict; } long lifetimeEvicted;
lock (_statusLock) { _evictedCount += toEvict; lifetimeEvicted = _evictedCount; }
_logger.Warning( _logger.Warning(
"Historian queue at capacity {Cap} — evicted {Count} oldest row(s) to make room (lifetime evictions: {Total})", "Historian queue at capacity {Cap} — evicted {Count} oldest row(s) to make room (lifetime evictions: {Total})",
_capacity, toEvict, _evictedCount); _capacity, toEvict, lifetimeEvicted);
} }
private void PurgeAgedDeadLetters(SqliteConnection conn) private void PurgeAgedDeadLetters(SqliteConnection conn)