using System.Collections.Concurrent;
using System.Diagnostics;
namespace SHH.MjpegPlayer
{
///
/// 设备配置同步处理器 (原 ConfigSyncManager 瘦身版)
/// 职责:仅负责确保远程分析节点(Instance)的摄像头配置与本地数据库一致。
/// 逻辑:通过 5 秒初始化冷却期避开抖动,并利用配置快照对比实现增量同步。
///
public class DeviceConfigHandler
{
#region 单例与核心存储字段
///
/// 获取配置处理器的全局单例实例
///
public static DeviceConfigHandler Instance { get; } = new DeviceConfigHandler();
///
/// 活跃服务实例 ID 集合 (InstanceId)
/// 用于记录当前所有已建立 gRpc 长连接的远程节点
///
private readonly ConcurrentHashSet _activeServiceIds = new ConcurrentHashSet();
///
/// 配置快照缓存:用于防止重复下发相同的配置
/// Key 格式: "InstanceId_CameraId"
/// Value: 该摄像头配置的 JSON 字符串快照
///
private readonly ConcurrentDictionary _lastSentConfigCache = new ConcurrentDictionary();
///
/// 后台监控任务的任务取消令牌源
///
private CancellationTokenSource _cts;
///
/// 初始化完成时间戳:用于 5 秒冷却期判定
/// 防止在服务刚启动或节点刚连接时,由于数据库加载延迟导致误判设备被移除
///
private DateTime _initCompleteTime = DateTime.MaxValue;
#endregion
#region 构造函数与初始化
///
/// 私有构造函数:订阅消息总线并启动监控任务
///
private DeviceConfigHandler()
{
// 订阅总线:仅关注节点注册事件,以此作为触发初始化全量同步的开关
MessageBus.Instance.OnServerRegistered += async (payload) =>
{
await HandleServiceOnlineAsync(payload.InstanceId);
};
// 启动后台轮询监控任务 (检测 Add/Update/Remove)
StartMonitorTask();
}
#endregion
#region 核心业务处理 (节点上线)
///
/// 处理新节点上线:执行全量同步
///
/// 远程服务实例唯一标识
private async Task HandleServiceOnlineAsync(string instanceId)
{
// 1. 将新实例记录到活跃列表
_activeServiceIds.Add(instanceId);
// 2. 预留 1 秒等待期,确保 gRpc 双向通道完全稳定
await Task.Delay(1000);
//// 3. 从数据库拍摄当前所有摄像头的快照
//var snapshot = CSdkStatics.DbCameras.ToList();
//// 4. 对新节点执行全量下发
//foreach (var cam in snapshot)
//{
// await SendSyncCommandAsync(instanceId, cam);
//}
// 5. 更新冷却期起始点
_initCompleteTime = DateTime.Now;
Debug.WriteLine($"[ConfigHandler] 节点 {instanceId} 初始化全量同步已完成。");
}
#endregion
#region 后台监控任务 (增量同步)
///
/// 启动后台增量监控任务
///
private void StartMonitorTask()
{
}
#endregion
}
}