wanshenmean
2026-03-19 cde6ad77663a80d78d77568428a6287b53347716
feat: 新增API路由缓存预热并完善机器人消息日志

变更内容:\n- 新增 ApiRouteCacheWarmupHostedService,在应用启动时统一预热 API 路由到缓存\n- 从 HttpClientHelper 构造函数中移除硬编码路由初始化逻辑,改为托管服务负责\n- Program.cs 注册 ApiRouteCacheWarmupHostedService,确保在启动阶段执行\n- RobotJob/RobotMessageHandler 注入 ILogger<RobotJob>,并在消息处理入口增加接收日志\n- WIDESEAWCS_Server.csproj 增加 logs 目录项\n\n变更原因:\n- 将路由缓存初始化从工具类构造器中解耦,避免隐式副作用,提升可维护性\n- 提升机器人通信链路可观测性,便于排查在线消息处理问题\n\n影响范围:\n- 缓存初始化路径:WIDESEAWCS_Core/Http/HTTP/HttpClientHelper.cs、WIDESEAWCS_Server/HostedService/*、Program.cs\n- 机器人消息处理链路:WIDESEAWCS_Tasks/RobotJob/RobotJob.cs、RobotMessageHandler.cs\n- 工程与本地环境文件:WIDESEAWCS_Server.csproj、.vs/DocumentLayout.json\n\n注意事项:\n- 本次包含 .vs 布局文件变更(开发环境文件)\n- 请上线前确认日志级别配置,避免生产环境日志量过大
已添加1个文件
已修改6个文件
212 ■■■■ 文件已修改
Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Http/HTTP/HttpClientHelper.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/HostedService/ApiRouteCacheWarmupHostedService.cs 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v18/DocumentLayout.json
@@ -3,16 +3,36 @@
  "WorkspaceRootPath": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\",
  "Documents": [
    {
      "AbsoluteMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_redisservice\\cache\\hybridcacheservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|solutionrelative:wideseawcs_redisservice\\cache\\hybridcacheservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_server\\hostedservice\\apiroutecachewarmuphostedservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}|WIDESEAWCS_Server\\WIDESEAWCS_Server.csproj|solutionrelative:wideseawcs_server\\hostedservice\\apiroutecachewarmuphostedservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_redisservice\\extensions\\redisservicesetup.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{F9886971-C3B2-4334-B014-D5109F2041DE}|WIDESEAWCS_RedisService\\WIDESEAWCS_RedisService.csproj|solutionrelative:wideseawcs_redisservice\\extensions\\redisservicesetup.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_core\\http\\http\\httpclienthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{BFFDD936-2E61-4D3A-ABFE-7CF77FE0B184}|WIDESEAWCS_Core\\WIDESEAWCS_Core.csproj|solutionrelative:wideseawcs_core\\http\\http\\httpclienthelper.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\workflow\\robotworkfloworchestrator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\workflow\\robotworkfloworchestrator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
      "AbsoluteMoniker": "D:0:0:{A14242DD-DA06-4DC3-8598-1761AA7C76D1}|WIDESEAWCS_SystemServices\\WIDESEAWCS_SystemServices.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_systemservices\\sys_dictionaryservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{A14242DD-DA06-4DC3-8598-1761AA7C76D1}|WIDESEAWCS_SystemServices\\WIDESEAWCS_SystemServices.csproj|solutionrelative:wideseawcs_systemservices\\sys_dictionaryservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotmessagehandler.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotmessagehandler.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    },
    {
      "AbsoluteMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|d:\\git\\shanmeixinnengyuan\\code\\wcs\\wideseawcs_server\\wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
      "RelativeMoniker": "D:0:0:{294E4915-0241-4C8C-BA99-7588B945863A}|WIDESEAWCS_Tasks\\WIDESEAWCS_Tasks.csproj|solutionrelative:wideseawcs_tasks\\robotjob\\robotjob.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
    }
  ],
  "DocumentGroupContainers": [
@@ -39,39 +59,106 @@
            {
              "$type": "Document",
              "DocumentIndex": 0,
              "Title": "HybridCacheService.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs",
              "RelativeToolTip": "WIDESEAWCS_RedisService\\Cache\\HybridCacheService.cs",
              "ViewState": "AgIAABcAAAAAAAAAAAAlwCoAAAAMAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-19T08:03:50.919Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 1,
              "Title": "ApiRouteCacheWarmupHostedService.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\HostedService\\ApiRouteCacheWarmupHostedService.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_Server\\HostedService\\ApiRouteCacheWarmupHostedService.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Server\\HostedService\\ApiRouteCacheWarmupHostedService.cs",
              "RelativeToolTip": "WIDESEAWCS_Server\\HostedService\\ApiRouteCacheWarmupHostedService.cs",
              "ViewState": "AgIAACMAAAAAAAAAAADwvzYAAAAlAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-19T08:01:46.997Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "Title": "RedisServiceSetup.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs",
              "RelativeToolTip": "WIDESEAWCS_RedisService\\Extensions\\RedisServiceSetup.cs",
              "ViewState": "AgIAADQAAAAAAAAAAAAqwCgAAAAAAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-19T07:52:38.709Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 3,
              "Title": "HttpClientHelper.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs",
              "RelativeToolTip": "WIDESEAWCS_Core\\Http\\HTTP\\HttpClientHelper.cs",
              "ViewState": "AgIAAA4AAAAAAAAAAAAowBoAAABNAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-19T07:48:09.389Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 5,
              "Title": "Sys_DictionaryService.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_SystemServices\\Sys_DictionaryService.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_SystemServices\\Sys_DictionaryService.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_SystemServices\\Sys_DictionaryService.cs",
              "RelativeToolTip": "WIDESEAWCS_SystemServices\\Sys_DictionaryService.cs",
              "ViewState": "AgIAADIAAAAAAAAAAAAYwFcAAAAQAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-19T07:47:06.312Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 4,
              "Title": "RobotWorkflowOrchestrator.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs*",
              "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs*",
              "ViewState": "AgIAAAAAAAAAAAAAAAAAACMAAABzAAAAAAAAAA==",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs",
              "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\Workflow\\RobotWorkflowOrchestrator.cs",
              "ViewState": "AgIAADEAAAAAAAAAAAAkwFcAAAAMAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-18T09:21:38.852Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 2,
              "DocumentIndex": 6,
              "Title": "RobotMessageHandler.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs",
              "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotMessageHandler.cs",
              "ViewState": "AgIAABMAAAAAAAAAAAAAwDIAAAAQAAAAAAAAAA==",
              "ViewState": "AgIAABYAAAAAAAAAAAAAwC0AAAAcAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-18T09:10:02.533Z"
              "WhenOpened": "2026-03-18T09:10:02.533Z",
              "EditorCaption": ""
            },
            {
              "$type": "Document",
              "DocumentIndex": 1,
              "DocumentIndex": 7,
              "Title": "RobotJob.cs",
              "DocumentMoniker": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
              "RelativeDocumentMoniker": "WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
              "ToolTip": "D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
              "RelativeToolTip": "WIDESEAWCS_Tasks\\RobotJob\\RobotJob.cs",
              "ViewState": "AgIAAEoAAAAAAAAAAAAAwGAAAAA7AAAAAAAAAA==",
              "ViewState": "AgIAADcAAAAAAAAAAAAiwEkAAAANAAAAAAAAAA==",
              "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
              "WhenOpened": "2026-03-18T08:56:41.452Z"
              "WhenOpened": "2026-03-18T08:56:41.452Z",
              "EditorCaption": ""
            }
          ]
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Http/HTTP/HttpClientHelper.cs
@@ -25,26 +25,6 @@
        {
            _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
            _cache = cache ?? throw new ArgumentNullException(nameof(cache));
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.CreateTaskInboundAsync)}", $"Task/CreateTaskInbound");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.GetTasksLocation)}", $"Task/GetTasksLocation");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.OutboundFinishTaskAsync)}", $"Task/OutboundFinishTask");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.InboundFinishTaskAsync)}", $"Task/InboundFinishTask");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.GetOutBoundTrayTaskAsync)}", $"Task/GetOutBoundTrayTask");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.CreateTaskInboundTrayAsync)}", $"Task/CreateTaskInboundTray");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.GroupPalletAsync)}", $"Stock/GroupPalletAsync");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.ChangePalletAsync)}", $"Stock/ChangePalletAsync");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.SplitPalletAsync)}", $"Stock/SplitPalletAsync");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.UpdateTaskByStatus)}", $"Task/UpdateTaskByStatus");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.TransferCheck)}", $"LocationInfo/TransferCheck");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.RelocationFinishTask)}", $"Task/RelocationFinishTask");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.CreateRobotGroupPalletTask)}", $"Task/CreateRobotGroupPalletTask");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.CreateRobotChangePalletTask)}", $"Task/CreateRobotChangePalletTask");
            _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.CreateRobotSplitPalletTask)}", $"Task/CreateRobotSplitPalletTask");
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/HostedService/ApiRouteCacheWarmupHostedService.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Core.Caches;
namespace WIDESEAWCS_Server.HostedService
{
    /// <summary>
    /// Preloads API route mappings into cache at application startup.
    /// </summary>
    public class ApiRouteCacheWarmupHostedService : IHostedService
    {
        private static readonly (string ConfigKey, string RoutePath)[] ApiRouteMappings =
        {
            (nameof(ConfigKey.CreateTaskInboundAsync), "Task/CreateTaskInbound"),
            (nameof(ConfigKey.GetTasksLocation), "Task/GetTasksLocation"),
            (nameof(ConfigKey.OutboundFinishTaskAsync), "Task/OutboundFinishTask"),
            (nameof(ConfigKey.InboundFinishTaskAsync), "Task/InboundFinishTask"),
            (nameof(ConfigKey.GetOutBoundTrayTaskAsync), "Task/GetOutBoundTrayTask"),
            (nameof(ConfigKey.CreateTaskInboundTrayAsync), "Task/CreateTaskInboundTray"),
            (nameof(ConfigKey.GroupPalletAsync), "Stock/GroupPalletAsync"),
            (nameof(ConfigKey.ChangePalletAsync), "Stock/ChangePalletAsync"),
            (nameof(ConfigKey.SplitPalletAsync), "Stock/SplitPalletAsync"),
            (nameof(ConfigKey.UpdateTaskByStatus), "Task/UpdateTaskByStatus"),
            (nameof(ConfigKey.TransferCheck), "LocationInfo/TransferCheck"),
            (nameof(ConfigKey.RelocationFinishTask), "Task/RelocationFinishTask"),
            (nameof(ConfigKey.CreateRobotGroupPalletTask), "Task/CreateRobotGroupPalletTask"),
            (nameof(ConfigKey.CreateRobotChangePalletTask), "Task/CreateRobotChangePalletTask"),
            (nameof(ConfigKey.CreateRobotSplitPalletTask), "Task/CreateRobotSplitPalletTask")
        };
        private readonly ICacheService _cache;
        private readonly ILogger<ApiRouteCacheWarmupHostedService> _logger;
        public ApiRouteCacheWarmupHostedService(
            ICacheService cache,
            ILogger<ApiRouteCacheWarmupHostedService> logger)
        {
            _cache = cache;
            _logger = logger;
        }
        public Task StartAsync(CancellationToken cancellationToken)
        {
            const string cacheKeyPrefix = $"{RedisPrefix.Code}:{RedisName.API}:";
            int warmedCount = 0;
            foreach ((string configKey, string routePath) in ApiRouteMappings)
            {
                _cache.TryAdd($"{cacheKeyPrefix}{configKey}", routePath);
                warmedCount++;
            }
            _logger.LogInformation(":API路由缓存预热完成。计数={Count}", warmedCount);
            return Task.CompletedTask;
        }
        public Task StopAsync(CancellationToken cancellationToken)
        {
            return Task.CompletedTask;
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs
@@ -80,6 +80,7 @@
builder.Services.AddMemoryCacheSetup(); // å†…存缓存
builder.Services.AddRedisSetup(builder.Configuration); // Redis ç¼“å­˜
builder.Services.AddHostedService<ApiRouteCacheWarmupHostedService>(); // API路由缓存预热(Redis就绪后加载)
builder.Services.AddSqlsugarSetup(); // SqlSugar æ•°æ®åº“配置
builder.Services.AddInitializationHostServiceSetup(); // åº”用初始化相关后台服务
builder.Services.AddHostedService<SeedDataHostedService>(); // å¯åŠ¨æ—¶ç§å­æ•°æ®åˆå§‹åŒ–
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj
@@ -108,6 +108,7 @@
    </ItemGroup>
    <ItemGroup>
      <Folder Include="logs\" />
      <Folder Include="Log\" />
    </ItemGroup>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
@@ -7,6 +7,7 @@
using WIDESEAWCS_Tasks.Workflow.Abstractions;
using WIDESEAWCS_Tasks.Workflow;
using WIDESEAWCS_Tasks.SocketServer;
using Microsoft.Extensions.Logging;
namespace WIDESEAWCS_Tasks
{
@@ -25,15 +26,18 @@
        private readonly IRobotMessageRouter _messageRouter;
        private readonly RobotTaskProcessor _taskProcessor;
        private readonly IRobotWorkflowOrchestrator _workflowOrchestrator;
        private readonly ILogger<RobotJob> _logger;
        public RobotJob(
            TcpSocketServer tcpSocket,
            IRobotTaskService robotTaskService,
            ITaskService taskService,
            ICacheService cache,
            HttpClientHelper httpClientHelper)
            HttpClientHelper httpClientHelper,
            ILogger<RobotJob> logger)
        {
            _stateManager = new RobotStateManager(cache);
            _logger = logger;
            // æ”¶å£ Socket è®¿é—®ï¼ŒåŽç»­è‹¥æ›¿æ¢é€šä¿¡å®žçŽ°åªéœ€æ›¿æ¢ç½‘å…³å±‚ã€‚
            ISocketClientGateway socketGateway = new SocketClientGateway(tcpSocket);
@@ -43,7 +47,7 @@
            var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor);
            var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway);
            _messageRouter = new RobotMessageHandler(socketGateway, _stateManager, cache, simpleCommandHandler, prefixCommandHandler);
            _messageRouter = new RobotMessageHandler(socketGateway, _stateManager, cache, simpleCommandHandler, prefixCommandHandler, logger);
            _workflowOrchestrator = new RobotWorkflowOrchestrator(_stateManager, _clientManager, _taskProcessor, robotTaskService);
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs
@@ -1,4 +1,5 @@
using System.Net.Sockets;
using Microsoft.Extensions.Logging;
using System.Net.Sockets;
using WIDESEAWCS_Common;
using WIDESEAWCS_Core.Caches;
using WIDESEAWCS_Tasks.Workflow.Abstractions;
@@ -15,19 +16,22 @@
        private readonly ICacheService _cache;
        private readonly IRobotSimpleCommandHandler _simpleCommandHandler;
        private readonly IRobotPrefixCommandHandler _prefixCommandHandler;
        private readonly ILogger<RobotJob> _logger;
        public RobotMessageHandler(
            ISocketClientGateway socketClientGateway,
            RobotStateManager stateManager,
            ICacheService cache,
            IRobotSimpleCommandHandler simpleCommandHandler,
            IRobotPrefixCommandHandler prefixCommandHandler)
            IRobotPrefixCommandHandler prefixCommandHandler,
            ILogger<RobotJob> logger)
        {
            _socketClientGateway = socketClientGateway;
            _stateManager = stateManager;
            _cache = cache;
            _simpleCommandHandler = simpleCommandHandler;
            _prefixCommandHandler = prefixCommandHandler;
            _logger = logger;
        }
        /// <summary>
@@ -35,6 +39,7 @@
        /// </summary>
        public async Task<string?> HandleMessageReceivedAsync(string message, bool isJson, TcpClient client, RobotSocketState state)
        {
            _logger.LogInformation($"接收到客户端【{state.RobotCrane.DeviceName}】发送消息【{message}】");
            var cacheKey = $"{RedisPrefix.Code}:{RedisName.SocketDevices}:{client.Client.RemoteEndPoint}";
            if (!_cache.TryGetValue(cacheKey, out RobotSocketState? cachedState) || cachedState == null)
            {