xxyy
2025-03-07 46ba61974b88fa75d1bcdad26709f2c3a945051e
新增 API 方法并实现请求节流机制

在 `TaskController.cs` 中添加多个新的 API 方法,并为其引入 `ThrottleFilter` 以限制请求频率。新增的方法包括 `CompleteTaskAsync`、`TransferCheckAsync` 等。

在 `CheckingStockOutMiddleware.cs` 中添加 `StockOutMiddleware`,定期调用 `StockCheckingAsync` 方法以检查库存状态。

在 `ThrottleFilter.cs` 中实现 `ThrottleFilter` 类,限制 API 方法的调用频率。

在 `appsettings.json` 中将 `UseRedis` 设置从 `true` 更改为 `false`,不再启用 Redis 缓存。
已修改2个文件
已添加2个文件
90 ■■■■ 文件已修改
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskController.cs 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Filter/CheckingStockOutMiddleware.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Filter/ThrottleFilter.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskController.cs
@@ -1,5 +1,4 @@
using WIDESEA_DTO;
using static WIDESEA_DTO.RequestTaskDto;
namespace WIDESEA_WMSServer.Controllers;
@@ -29,21 +28,11 @@
    /// <param name="saveModel">任务号</param>
    /// <returns>成功或失败</returns>
    [HttpGet, Route("CompleteTaskAsync"), AllowAnonymous]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> CompleteTaskAsync(int taskNum)
    {
        return await _taskService.CompleteAsync(taskNum);
    }
    /// <summary>
    /// ä»»åŠ¡å®Œæˆ
    /// </summary>
    /// <param name="saveModel">任务号</param>
    /// <returns>成功或失败</returns>
    //[HttpGet, Route("CompleteTaskByStation"), AllowAnonymous]
    //public async Task<WebResponseContent> CompleteTaskByStation(int taskNum)
    //{
    //    return await _taskService.CompleteTaskByStation(taskNum);
    //}
    /// <summary>
    /// æ£€æŸ¥æ˜¯å¦éœ€è¦è¿›è¡Œç§»åº“
@@ -51,6 +40,7 @@
    /// <param name="taskNum">任务号</param>
    /// <returns>任务</returns>
    [HttpGet, Route("TransferCheckAsync"), AllowAnonymous]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> TransferCheckAsync(int taskNum)
    {
        return new WebResponseContent().OK(data: await _locationService.TransferCheckAsync(taskNum));
@@ -62,6 +52,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("RequestTaskAsync")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> RequestTaskAsync([FromBody] RequestTaskDto input)
    {
        return await Service.RequestTaskAsync(input);
@@ -73,6 +64,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("RequestInTask")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> RequestInTask([FromBody] RequestTaskDto input)
    {
        return await Service.RequestInTask(input);
@@ -84,6 +76,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("RequestLocationTaskAsync")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> UpdateExistingTask([FromBody] RequestTaskDto input)
    {
        return await Service.UpdateExistingTask(input);
@@ -95,17 +88,19 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("RequestTrayInTaskAsync")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> RequestTrayInTaskAsync([FromBody] RequestTaskDto input)
    {
        return await Service.RequestTrayInTaskAsync(input);
    }
    /// <summary>
    /// ç©ºæ‰˜ç›˜&满盘出库请求
    /// ç©ºæ‰˜ç›˜æ»¡ç›˜å‡ºåº“请求
    /// </summary>
    /// <param name="request">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("RequestTrayOutTaskAsync")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> RequestTrayOutTaskAsync([FromBody] RequestOutTaskDto request)
    {
        return await Service.RequestTrayOutTaskAsync(request.Position, request.Tag, request.AreaCdoe, request.AreaCdoes, request.ProductionLine);
@@ -117,6 +112,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("UpdateTaskStatus")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> UpdateTaskStatus([FromBody] UpdateStatusDto input)
    {
        return await Service.UpdateTaskStatus(input.TaskNum, input.TaskState);
@@ -128,6 +124,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpGet, AllowAnonymous, Route("StockCheckingAsync")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public WebResponseContent StockCheckingAsync()
    {
        return Service.StockCheckingAsync();
@@ -140,6 +137,7 @@
    /// <param name="palletCode">托盘号</param>
    /// <returns></returns>
    [HttpGet, AllowAnonymous, Route("CreateAndSendOutboundTask")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> CreateAndSendOutboundTask(string locationCode, string palletCode)
    {
        return await Service.CreateAndSendOutboundTask(locationCode, palletCode);
@@ -152,6 +150,7 @@
    /// <param name="palletCode">托盘号</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("RequestInBoundTaskNG")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> RequestInBoundTaskNG([FromBody] RequestTaskDto input)
    {
        return await Service.CreateAndSendInboundTask(input.PalletCode, input.Position);
@@ -163,6 +162,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("GetFROutTrayToCW")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> GetFROutTrayToCW([FromBody] RequestTaskDto input)
    {
        return await Service.GetFROutTrayToCW(input);
@@ -174,11 +174,11 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("EmergencyTask")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public WebResponseContent EmergencyTask([FromBody] object input)
    {
        return Service.EmergencyTask(input);
    }
    /// <summary>
    /// CW3 å‡ºåº“至包装
@@ -186,6 +186,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("RequestOutTaskToBZAsync")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> RequestOutTaskToBZAsync([FromBody] RequestTaskDto input)
    {
        return await Service.RequestOutTaskToBZAsync(input);
@@ -197,6 +198,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("SetEmptyOutbyInToOutAsync")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> SetEmptyOutbyInToOutAsync([FromBody] RequestTaskDto input)
    {
        return await Service.SetEmptyOutbyInToOutAsync(input);
@@ -208,6 +210,7 @@
    /// <param name="input">请求数据</param>
    /// <returns></returns>
    [HttpPost, AllowAnonymous, Route("SetEmptyOutbyInToOutOneAsync")]
    [TypeFilter(typeof(ThrottleFilter), Arguments = new object[] { 5 })] // 5秒节流
    public async Task<WebResponseContent> SetEmptyOutbyInToOutOneAsync([FromBody] RequestTaskDto input)
    {
        return await Service.SetEmptyOutbyInToOutOneAsync(input);
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Filter/CheckingStockOutMiddleware.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@

using WIDESEA_Core.Middlewares;
using WIDESEA_IStorageTaskServices;
using WIDESEA_StorageOutTaskServices;
namespace WIDESEA_WMSServer.Filter
{
    public static class StockOutMiddleware
    {
        public static Task InvokeAsync()
        {
            Task.Run(() =>
            {
                while (true)
                {
                    var _taskService = WIDESEA_Core.App.GetService<IDt_TaskService>();
                    if (_taskService != null)
                    {
                        _taskService.StockCheckingAsync();
                    }
                    Thread.Sleep(10000);
                }
            });
            return Task.CompletedTask;
        }
    }
}
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Filter/ThrottleFilter.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
using Microsoft.AspNetCore.Mvc.Filters;
using System.Collections.Concurrent;
public class ThrottleFilter : IAsyncActionFilter
{
    private static readonly ConcurrentDictionary<string, DateTime> _lastExecutionTimes = new ConcurrentDictionary<string, DateTime>();
    private readonly int _intervalInSeconds;
    public ThrottleFilter(int intervalInSeconds)
    {
        _intervalInSeconds = intervalInSeconds;
    }
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var actionName = context.ActionDescriptor.DisplayName;
        if (_lastExecutionTimes.TryGetValue(actionName, out var lastExecutionTime))
        {
            var elapsedTime = DateTime.Now - lastExecutionTime;
            if (elapsedTime.TotalSeconds < _intervalInSeconds)
            {
                context.Result = new Microsoft.AspNetCore.Mvc.StatusCodeResult(429);
                return;
            }
        }
        _lastExecutionTimes[actionName] = DateTime.Now;
        await next();
    }
}
Code Management/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
@@ -27,7 +27,7 @@
  //缓存设置
  "CacheSettings": {
    "UseRedis": true, //启用redis
    "UseRedis": false, //启用redis
    "RedisSettings": {
      "Address": "127.0.0.1:6379", //地址
      "Password": "123456", //Redis服务密码