wanshenmean
2026-03-17 94ad631d316da04c46266ddb1fc6e63e6f8f2fae
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
using Newtonsoft.Json;
using WIDESEAWCS_Common;
using WIDESEAWCS_Core.Caches;
using WIDESEAWCS_QuartzJob;
 
namespace WIDESEAWCS_Tasks
{
    /// <summary>
    /// 机械手状态管理器 - 负责RobotSocketState的安全更新和克隆
    /// </summary>
    public class RobotStateManager
    {
        private readonly ICacheService _cache;
 
        public RobotStateManager(ICacheService cache)
        {
            _cache = cache;
        }
 
        /// <summary>
        /// 安全更新RobotSocketState缓存,防止并发覆盖
        /// </summary>
        /// <param name="ipAddress">设备IP地址</param>
        /// <param name="updateAction">更新状态的委托(传入当前状态,返回修改后的新状态)</param>
        /// <returns>是否更新成功</returns>
        public bool TryUpdateStateSafely(string ipAddress, Func<RobotSocketState, RobotSocketState> updateAction)
        {
            var cacheKey = GetCacheKey(ipAddress);
            var currentState = _cache.Get<RobotSocketState>(cacheKey);
 
            if (currentState == null)
            {
                return false;
            }
 
            // 使用当前存储的版本号作为期望版本
            var expectedVersion = currentState.Version;
 
            // 创建状态副本进行修改(避免修改原对象引用)
            var stateCopy = CloneState(currentState);
            var newState = updateAction(stateCopy);
            newState.Version = DateTime.UtcNow.Ticks;
 
            return _cache.TrySafeUpdate(
                cacheKey,
                newState,
                expectedVersion,
                s => s.Version
            );
        }
 
        /// <summary>
        /// 安全更新RobotSocketState缓存(简单版本)
        /// </summary>
        /// <param name="ipAddress">设备IP地址</param>
        /// <param name="newState">新状态(会被更新Version字段)</param>
        /// <returns>是否更新成功</returns>
        public bool TryUpdateStateSafely(string ipAddress, RobotSocketState newState)
        {
            var cacheKey = GetCacheKey(ipAddress);
            var currentState = _cache.Get<RobotSocketState>(cacheKey);
 
            if (currentState == null)
            {
                // 当前不存在,直接添加
                newState.Version = DateTime.UtcNow.Ticks;
                _cache.AddObject(cacheKey, newState);
                return true;
            }
 
            // 使用当前存储的版本号作为期望版本
            var expectedVersion = currentState.Version;
 
            // 更新新状态的版本号为最新时间戳
            newState.Version = DateTime.UtcNow.Ticks;
 
            return _cache.TrySafeUpdate(
                cacheKey,
                newState,
                expectedVersion,
                s => s.Version
            );
        }
 
        /// <summary>
        /// 克隆RobotSocketState对象(创建深拷贝)
        /// </summary>
        public RobotSocketState CloneState(RobotSocketState source)
        {
            // 使用序列化/反序列化进行深拷贝
            var json = JsonConvert.SerializeObject(source);
            return JsonConvert.DeserializeObject<RobotSocketState>(json) ?? new RobotSocketState { IPAddress = source.IPAddress };
        }
 
        /// <summary>
        /// 获取Redis缓存键
        /// </summary>
        public static string GetCacheKey(string ipAddress)
        {
            return $"{RedisPrefix.Code}:{RedisName.SocketDevices}:{ipAddress}";
        }
 
        /// <summary>
        /// 从缓存获取状态
        /// </summary>
        public RobotSocketState? GetState(string ipAddress)
        {
            return _cache.Get<RobotSocketState>(GetCacheKey(ipAddress));
        }
 
        /// <summary>
        /// 获取或创建状态
        /// </summary>
        public RobotSocketState GetOrCreateState(string ipAddress, RobotCraneDevice robotCrane)
        {
            return _cache.GetOrAdd(GetCacheKey(ipAddress), _ => new RobotSocketState
            {
                IPAddress = ipAddress,
                RobotCrane = robotCrane
            });
        }
    }
}