using Microsoft.Extensions.Options; using System.Collections.Concurrent; using YD_TrainingCompetition_Api.Models; using YD_TrainingCompetition_Api.Options; namespace YD_TrainingCompetition_Api.Services; public sealed class HikvisionAlarmStore : IHikvisionAlarmStore { private readonly ConcurrentQueue _alarms = new(); private readonly ConcurrentDictionary _cameraStatuses = new(StringComparer.OrdinalIgnoreCase); private readonly HikvisionOptions _options; private readonly ILogger _logger; private int _alarmCount; public HikvisionAlarmStore(IOptions options, ILogger logger) { _options = options.Value; _logger = logger; } public void Add(AlarmRecord record) { _alarms.Enqueue(record); var newCount = Interlocked.Increment(ref _alarmCount); // 超出上限则移除最旧的记录 while (newCount > _options.MaxAlarmRecords) { if (_alarms.TryDequeue(out _)) { Interlocked.Decrement(ref _alarmCount); newCount--; } } _logger.LogInformation("Alarm stored: DeviceId={DeviceId}, Id={Id}, QueueSize={Size}", record.DeviceId, record.Id, newCount); } public IReadOnlyCollection GetAll() { return _alarms.Reverse().ToArray(); } public IReadOnlyCollection GetByDeviceId(string deviceId) { return _alarms .Where(x => string.Equals(x.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase)) .Reverse() .ToArray(); } public AlarmRecord? GetLatest() { return _alarms.LastOrDefault(); } public AlarmRecord? GetLatestByDevice(string deviceId) { return _alarms .LastOrDefault(x => string.Equals(x.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase)); } public void UpdateCameraStatus(HikvisionCameraStatus status) { status.LastSeen = DateTimeOffset.UtcNow; _cameraStatuses[status.DeviceId] = status; } public IReadOnlyCollection GetAllCameraStatuses() { return _cameraStatuses.Values .OrderBy(x => x.DeviceId, StringComparer.OrdinalIgnoreCase) .ToArray(); } public HikvisionCameraStatus? GetCameraStatus(string deviceId) { return _cameraStatuses.TryGetValue(deviceId, out var status) ? status : null; } public void ClearAlarms() { while (_alarms.TryDequeue(out _)) { Interlocked.Decrement(ref _alarmCount); } _logger.LogInformation("All alarms cleared"); } }