xf vor 2 Jahren
Ursprung
Commit
4cd28423ba

+ 16 - 4
src/Hotline.Api/Controllers/TestController.cs

@@ -28,6 +28,7 @@ using XF.Domain.Authentications;
 using XF.Domain.Cache;
 using XF.Domain.Entities;
 using XF.Domain.Exceptions;
+using XF.Domain.Locks;
 
 namespace Hotline.Api.Controllers;
 
@@ -52,12 +53,13 @@ public class TestController : BaseController
     private readonly IMediator _mediator;
 
     private readonly ITimeLimitApplication _timeLimitApplication;
+    private readonly IDistributedLock _distributedLock;
     private readonly IGroupManager _goupManager;
 
     //private readonly ITypedCache<List<User>> _cache;
     //private readonly ICacheManager<User> _cache;
 
-    
+
     public TestController(
         INewRockClient client,
         ILogger<TestController> logger,
@@ -75,7 +77,7 @@ public class TestController : BaseController
         IRoleRepository roleRepository,
         IMediator mediator,
         ITimeLimitApplication timeLimitApplication,
-        IGroupManager groupManager
+        IDistributedLock distributedLock
     )
     {
         _logger = logger;
@@ -91,8 +93,7 @@ public class TestController : BaseController
         _roleRepository = roleRepository;
         _mediator = mediator;
         _timeLimitApplication = timeLimitApplication;
-
-        groupManager.AddToGroupAsync("123", "123");
+        _distributedLock = distributedLock;
     }
 
     [HttpGet("pgsql")]
@@ -115,6 +116,17 @@ public class TestController : BaseController
     [HttpGet("roles")]
     public async Task<List<Role>> GetRoles()
     {
+        using var lockManager = new LockManager(_distributedLock, $"{nameof(TestController)}.{nameof(GetRoles)}");
+        lockManager.InvokeInLock(() =>
+        {
+            Console.WriteLine("do something");
+        }, TimeSpan.FromSeconds(10));
+
+        await lockManager.InvokeInLockAsync(
+            d => _roleRepository.Queryable(includeDeleted: true).ToListAsync(), 
+            TimeSpan.FromSeconds(10),
+            HttpContext.RequestAborted);
+
         var a = await _roleRepository.Queryable()
             //.Where(d => !d.IsDeleted)
             .ToListAsync();

+ 5 - 0
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -286,6 +286,11 @@ namespace Hotline.Share.Dtos.Order
 
         #endregion
 
+        /// <summary>
+        /// 来源,区分省平台或110等其他平台同步过来的工单
+        /// </summary>
+        public ESource Source { get; set; }
+
         /// <summary>
         /// 投诉
         /// </summary>

+ 9 - 9
src/Hotline.Share/Enums/Order/EAcceptType.cs

@@ -7,42 +7,42 @@ namespace Hotline.Share.Enums.Order;
 /// </summary>
 public enum EAcceptType
 {
-    [Description("其他")]
-    Other = 0,
-
     /// <summary>
     /// 咨询
     /// </summary>
     [Description("咨询")]
-    Consult = 1,
+    Consult = 10,
 
     /// <summary>
     /// 建议
     /// </summary>
     [Description("建议")]
-    Suggest = 2,
+    Suggest = 15,
 
     /// <summary>
     /// 求助
     /// </summary>
     [Description("求助")]
-    SeekHelp = 3,
+    SeekHelp = 20,
 
     /// <summary>
     /// 表扬
     /// </summary>
     [Description("表扬")]
-    Praise = 4,
+    Praise = 25,
 
     /// <summary>
     /// 举报
     /// </summary>
     [Description("举报")]
-    Report = 5,
+    Report = 30,
 
     /// <summary>
     /// 投诉
     /// </summary>
     [Description("投诉")]
-    Complain = 6,
+    Complain = 35,
+
+    [Description("其他")]
+    Other = 40,
 }

+ 19 - 0
src/Hotline.Share/Enums/Order/ESource.cs

@@ -0,0 +1,19 @@
+namespace Hotline.Share.Enums.Order;
+
+public enum ESource
+{
+    /// <summary>
+    /// 热线平台工单
+    /// </summary>
+    Normal = 0,
+
+    /// <summary>
+    /// 省平台直派
+    /// </summary>
+    ProvinceStraight = 10,
+
+    /// <summary>
+    /// 110同步工单
+    /// </summary>
+    Police110 = 20,
+}

+ 5 - 0
src/Hotline/Orders/Order.cs

@@ -225,6 +225,11 @@ namespace Hotline.Orders
         /// </summary>
         public EExpiredStatus ExpiredStatus { get; set; }
 
+        /// <summary>
+        /// 来源,区分省平台或110等其他平台同步过来的工单
+        /// </summary>
+        public ESource Source { get; set; }
+
         #endregion
 
         /// <summary>

+ 87 - 0
src/XF.Domain/Locks/IDistributedLock.cs

@@ -0,0 +1,87 @@
+using Microsoft.AspNetCore.DataProtection.KeyManagement;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Exceptions;
+
+namespace XF.Domain.Locks
+{
+    public interface IDistributedLock
+    {
+        public bool Acquire(string key, TimeSpan expired);
+
+        public Task<bool> AcquireAsync(string key, TimeSpan expired, CancellationToken cancellationToken);
+
+        public void Release(string key);
+
+        public Task ReleaseAsync(string key, CancellationToken cancellationToken);
+    }
+
+    public class LockManager : IDisposable
+    {
+        private readonly IDistributedLock _locker;
+        private readonly string _key;
+
+        public LockManager(IDistributedLock locker, string key)
+        {
+            _locker = locker;
+            _key = key;
+        }
+
+        /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
+        public void Dispose()
+        {
+            _locker.Release(_key);
+        }
+
+        public void InvokeInLock(Action doSome, TimeSpan expired)
+        {
+            if (_locker.Acquire(_key, expired))
+            {
+                try
+                {
+                    doSome();
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine(e);
+                    throw;
+                }
+                finally
+                {
+                    _locker.Release(_key);
+                }
+            }
+            else
+            {
+                throw new UserFriendlyException("系统忙,请稍后重试");
+            }
+        }
+
+        public async Task InvokeInLockAsync(Func<CancellationToken, Task> doSome, TimeSpan expired, CancellationToken cancellationToken)
+        {
+            if (await _locker.AcquireAsync(_key, expired, cancellationToken))
+            {
+                try
+                {
+                    await doSome(cancellationToken);
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine(e);
+                    throw;
+                }
+                finally
+                {
+                    await _locker.ReleaseAsync(_key, cancellationToken);
+                }
+            }
+            else
+            {
+                throw new UserFriendlyException("系统忙,请稍后重试");
+            }
+        }
+    }
+}

+ 31 - 0
src/XF.EasyCaching/DefaultDistributedLock.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using EasyCaching.Core;
+using XF.Domain.Dependency;
+using XF.Domain.Locks;
+
+namespace XF.EasyCaching
+{
+    public class DefaultDistributedLock : IDistributedLock, IScopeDependency
+    {
+        private readonly IRedisCachingProvider _redisCaching;
+
+        public DefaultDistributedLock(IRedisCachingProvider redisCaching)
+        {
+            _redisCaching = redisCaching;
+        }
+
+        public bool Acquire(string key, TimeSpan expired) => 
+            _redisCaching.StringSet(key, key, expired, "nx");
+
+        public async Task<bool> AcquireAsync(string key, TimeSpan expired, CancellationToken cancellationToken) => 
+            await _redisCaching.StringSetAsync(key, key, expired, "nx");
+
+        public void Release(string key) => _redisCaching.KeyDel(key);
+
+        public async Task ReleaseAsync(string key, CancellationToken cancellationToken) => await _redisCaching.KeyDelAsync(key);
+    }
+}