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- 请上线前确认日志级别配置,避免生产环境日志量过大
| | |
| | | "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": [ |
| | |
| | | { |
| | | "$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": "" |
| | | } |
| | | ] |
| | | } |
| | |
| | | { |
| | | _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> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | 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>(); // å¯å¨æ¶ç§åæ°æ®åå§å |
| | |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Folder Include="logs\" /> |
| | | <Folder Include="Log\" /> |
| | | </ItemGroup> |
| | | |
| | |
| | | using WIDESEAWCS_Tasks.Workflow.Abstractions; |
| | | using WIDESEAWCS_Tasks.Workflow; |
| | | using WIDESEAWCS_Tasks.SocketServer; |
| | | using Microsoft.Extensions.Logging; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | | { |
| | |
| | | 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); |
| | |
| | | |
| | | 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); |
| | | |
| | |
| | | using System.Net.Sockets; |
| | | using Microsoft.Extensions.Logging; |
| | | using System.Net.Sockets; |
| | | using WIDESEAWCS_Common; |
| | | using WIDESEAWCS_Core.Caches; |
| | | using WIDESEAWCS_Tasks.Workflow.Abstractions; |
| | |
| | | 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> |
| | |
| | | /// </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) |
| | | { |