From 9d1660270272180cd71147d6ddd53d1382643d2e Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 02 十一月 2026 18:00:14 +0800
Subject: [PATCH] merge: 并入远程 Initial commit 作为历史根节点
---
Plugin.DeviceDebug/Model/DebugSessionManager.cs | 380 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 380 insertions(+), 0 deletions(-)
diff --git a/Plugin.DeviceDebug/Model/DebugSessionManager.cs b/Plugin.DeviceDebug/Model/DebugSessionManager.cs
new file mode 100644
index 0000000..334c0b1
--- /dev/null
+++ b/Plugin.DeviceDebug/Model/DebugSessionManager.cs
@@ -0,0 +1,380 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using log4net;
+using Plugin.DeviceDebug.Entity;
+using Aging.Infrastructure.Contracts;
+
+namespace Plugin.DeviceDebug.Model
+{
+ /// <summary>
+ /// 璋冭瘯浼氳瘽绠$悊鍣� - 璐熻矗鐘舵�佹満杞崲鍜屾潈闄愭牎楠�
+ /// </summary>
+ public class DebugSessionManager
+ {
+ private static readonly ILog log = LogManager.GetLogger(typeof(DebugSessionManager));
+ private readonly DeviceDebugModel _model;
+ private readonly IResourceManager? _resourceManager;
+
+ // 鍐呭瓨涓殑娲昏穬浼氳瘽缂撳瓨
+ private readonly Dictionary<string, DebugSession> _activeSessions = new();
+
+ public DebugSessionManager(DeviceDebugModel model, IResourceManager? resourceManager = null)
+ {
+ _model = model;
+ _resourceManager = resourceManager;
+ }
+
+ /// <summary>
+ /// 鎵撳紑浼氳瘽锛圧eadOnly妯″紡锛�
+ /// </summary>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// 璇锋眰杩涘叆缁存姢妯″紡锛圧eadOnly 鈫� AcquiringMaintenance锛�
+ /// 妫�鏌ワ細璁惧鏄惁鏈夌敓浜eserved
+ /// </summary>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// 婵�娲荤淮鎶ゆā寮忥紙AcquiringMaintenance 鈫� MaintenanceActive锛�
+ /// </summary>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// 鍏抽棴浼氳瘽锛圡aintenanceActive 鈫� Closing 鈫� Closed锛�
+ /// 鎵ц瀹夊叏鐘舵�佹鏌�
+ /// </summary>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// 鏁呴殰澶勭悊锛堜换鎰� 鈫� Faulted锛�
+ /// </summary>
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// 鏍囪闇�瑕佹仮澶嶏紙浠绘剰 鈫� RecoveryRequired锛�
+ /// </summary>
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// 楠岃瘉鍛戒护鏄惁鍏佽鎵ц锛堝彧鏈� MaintenanceActive 鐘舵�佸厑璁稿啓鎿嶄綔锛�
+ /// </summary>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇浼氳瘽鐘舵��
+ /// </summary>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// 鑾峰彇璁惧褰撳墠浼氳瘽锛堝鏋滄湁锛�
+ /// </summary>
+ 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;
+ }
+ }
+ }
+}
--
Gitblit v1.9.1