using System; using System.Collections.Generic; using System.Linq; using log4net; using Plugin.DeviceDebug.Entity; using Aging.Infrastructure.Contracts; namespace Plugin.DeviceDebug.Model { /// /// 调试会话管理器 - 负责状态机转换和权限校验 /// public class DebugSessionManager { private static readonly ILog log = LogManager.GetLogger(typeof(DebugSessionManager)); private readonly DeviceDebugModel _model; private readonly IResourceManager? _resourceManager; // 内存中的活跃会话缓存 private readonly Dictionary _activeSessions = new(); public DebugSessionManager(DeviceDebugModel model, IResourceManager? resourceManager = null) { _model = model; _resourceManager = resourceManager; } /// /// 打开会话(ReadOnly模式) /// public DebugSession OpenSession(string deviceId, string operatorId, string operatorName, string effectiveVersion) { try { // 检查是否已有活跃会话 var existingSession = GetActiveSessionByDevice(deviceId); if (existingSession != null) { log.Warn($"设备 {deviceId} 已有活跃会话: {existingSession.SessionId}"); return existingSession; } var session = new DebugSession { DeviceId = deviceId, OperatorId = operatorId, OperatorName = operatorName, EffectiveVersion = effectiveVersion, State = DebugSessionState.ReadOnly }; // 持久化到数据库 _model.CreateSession(session); // 更新内存缓存 _activeSessions[session.SessionId] = session; log.Info($"打开会话: {session.SessionId}, 设备: {deviceId}, 操作员: {operatorName}"); return session; } catch (Exception ex) { log.Error($"打开会话失败: {ex.Message}", ex); throw; } } /// /// 请求进入维护模式(ReadOnly → AcquiringMaintenance) /// 检查:设备是否有生产Reserved /// public bool RequestMaintenance(string sessionId) { try { if (!_activeSessions.TryGetValue(sessionId, out var session)) { log.Warn($"会话不存在: {sessionId}"); return false; } // 验证状态转换 if (session.State != DebugSessionState.ReadOnly) { log.Warn($"会话 {sessionId} 当前状态为 {session.State},无法请求维护模式"); return false; } // 检查设备是否有生产Reserved(与资源预约系统集成) if (_resourceManager != null) { var resourceKey = new ResourceKey(session.DeviceId, "Generic"); var ownerToken = new ResourceOwnerToken(OwnerType.Maintenance, session.SessionId); try { var reservation = _resourceManager.ReserveAsync( ownerToken, resourceKey, CancellationToken.None).GetAwaiter().GetResult(); session.ReservationRef = reservation.ReservationId; } catch (ResourceConflictException) { log.Warn($"设备 {session.DeviceId} 已被生产预约占用,拒绝维护请求"); return false; } } else { // 降级模式:无 ResourceManager 时允许所有请求(向后兼容) log.Warn("ResourceManager 未初始化,跳过资源预约检查"); } // 状态转换 session.State = DebugSessionState.AcquiringMaintenance; // 持久化 _model.UpdateSession(session); log.Info($"会话 {sessionId} 请求维护模式"); return true; } catch (Exception ex) { log.Error($"请求维护模式失败: {ex.Message}", ex); return false; } } /// /// 激活维护模式(AcquiringMaintenance → MaintenanceActive) /// public void ActivateMaintenance(string sessionId) { try { if (!_activeSessions.TryGetValue(sessionId, out var session)) { log.Warn($"会话不存在: {sessionId}"); throw new InvalidOperationException($"会话不存在: {sessionId}"); } // 验证状态转换 if (session.State != DebugSessionState.AcquiringMaintenance) { log.Warn($"会话 {sessionId} 当前状态为 {session.State},无法激活维护模式"); throw new InvalidOperationException($"会话 {sessionId} 当前状态为 {session.State},无法激活维护模式"); } // 状态转换 session.State = DebugSessionState.MaintenanceActive; // 持久化 _model.UpdateSession(session); log.Info($"会话 {sessionId} 激活维护模式"); } catch (Exception ex) { log.Error($"激活维护模式失败: {ex.Message}", ex); throw; } } /// /// 关闭会话(MaintenanceActive → Closing → Closed) /// 执行安全状态检查 /// public void CloseSession(string sessionId) { try { if (!_activeSessions.TryGetValue(sessionId, out var session)) { log.Warn($"会话不存在: {sessionId}"); throw new InvalidOperationException($"会话不存在: {sessionId}"); } // 验证状态转换(只有 MaintenanceActive 可以关闭) if (session.State != DebugSessionState.MaintenanceActive) { log.Warn($"会话 {sessionId} 当前状态为 {session.State},无法关闭"); throw new InvalidOperationException($"会话 {sessionId} 当前状态为 {session.State},无法关闭"); } // 状态转换: MaintenanceActive → Closing session.State = DebugSessionState.Closing; _model.UpdateSession(session); log.Debug($"会话 {sessionId} 进入关闭中状态"); // 执行安全状态检查:释放资源预约 if (_resourceManager != null && !string.IsNullOrEmpty(session.ReservationRef)) { try { var resourceKey = new ResourceKey(session.DeviceId, "Generic"); var ownerToken = new ResourceOwnerToken(OwnerType.Maintenance, session.SessionId); _resourceManager.ReleaseReservationAsync( ownerToken, resourceKey, CancellationToken.None).GetAwaiter().GetResult(); log.Info($"已释放设备 {session.DeviceId} 的资源预约"); } catch (Exception ex) { log.Error($"释放资源预约失败: {ex.Message}", ex); // 不阻止关闭流程,但记录警告 } } // 状态转换: Closing → Closed session.State = DebugSessionState.Closed; session.ClosedAt = DateTime.Now; _model.UpdateSession(session); // 从缓存中移除 _activeSessions.Remove(sessionId); log.Info($"会话 {sessionId} 已关闭"); } catch (Exception ex) { log.Error($"关闭会话失败: {ex.Message}", ex); throw; } } /// /// 故障处理(任意 → Faulted) /// public void FaultSession(string sessionId, string errorMessage) { try { if (!_activeSessions.TryGetValue(sessionId, out var session)) { log.Warn($"会话不存在: {sessionId}"); return; } // 记录当前状态 var previousState = session.State; // 状态转换 session.State = DebugSessionState.Faulted; // 持久化 _model.UpdateSession(session); log.Error($"会话 {sessionId} 发生故障,从 {previousState} 转为 Faulted: {errorMessage}"); } catch (Exception ex) { log.Error($"标记故障状态失败: {ex.Message}", ex); } } /// /// 标记需要恢复(任意 → RecoveryRequired) /// public void MarkRecoveryRequired(string sessionId) { try { if (!_activeSessions.TryGetValue(sessionId, out var session)) { log.Warn($"会话不存在: {sessionId}"); return; } // 记录当前状态 var previousState = session.State; // 状态转换 session.State = DebugSessionState.RecoveryRequired; // 持久化 _model.UpdateSession(session); log.Warn($"会话 {sessionId} 标记为需要恢复,从 {previousState} 转为 RecoveryRequired"); } catch (Exception ex) { log.Error($"标记恢复状态失败: {ex.Message}", ex); } } /// /// 验证命令是否允许执行(只有 MaintenanceActive 状态允许写操作) /// public bool ValidateCommand(string sessionId, DebugCommand command) { try { if (!_activeSessions.TryGetValue(sessionId, out var session)) { log.Warn($"会话不存在: {sessionId}"); return false; } // 只有 MaintenanceActive 状态允许写操作 bool allowed = session.State == DebugSessionState.MaintenanceActive; if (!allowed) { log.Warn($"会话 {sessionId} 状态为 {session.State},拒绝执行命令: {command.CommandType}"); } // 增加资源预约验证 if (allowed && _resourceManager != null) { var resourceKey = new ResourceKey(session.DeviceId, "Generic"); allowed = _resourceManager.ValidateOwner( new ResourceOwnerToken(OwnerType.Maintenance, session.SessionId), resourceKey); if (!allowed) { log.Warn($"会话 {sessionId} 资源预约验证失败,拒绝执行命令: {command.CommandType}"); } } return allowed; } catch (Exception ex) { log.Error($"验证命令失败: {ex.Message}", ex); return false; } } /// /// 获取会话状态 /// public DebugSessionState? GetSessionState(string sessionId) { try { if (_activeSessions.TryGetValue(sessionId, out var session)) { return session.State; } // 从数据库查询 var dbSession = _model.GetSession(sessionId); return dbSession?.State; } catch (Exception ex) { log.Error($"获取会话状态失败: {ex.Message}", ex); return null; } } /// /// 获取设备当前会话(如果有) /// public DebugSession? GetActiveSessionByDevice(string deviceId) { try { // 先从内存缓存查找 var cachedSession = _activeSessions.Values .FirstOrDefault(s => s.DeviceId == deviceId && s.State != DebugSessionState.Closed); if (cachedSession != null) { return cachedSession; } // 从数据库查询 var activeSessions = _model.GetActiveSessionsByDevice(deviceId); return activeSessions.FirstOrDefault(); } catch (Exception ex) { log.Error($"获取设备活跃会话失败: {ex.Message}", ex); return null; } } } }