For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 在 RouterService 中引入 HybridCacheService 混合缓存,第一次查询加载全量路由到缓存,后续查询直接从缓存读取,AddRouters 写入后同步更新缓存。
Architecture: 按 InOutType 分开缓存两份(入口/出口),GetOrAdd 懒加载,写穿更新缓存,单实例部署无广播需求。
Tech Stack: ASP.NET Core 6.0, HybridCacheService, SqlSugar ORM
修改文件:
- WIDESEAWCS_QuartzJob/Service/RouterService.cs — 全部缓存逻辑改动
不变:
- FindRoutesInMemory — 只改调用方,算法逻辑不变
- QueryAllPositions — 已有独立缓存,不依赖本方案
文件:
- Modify: WIDESEAWCS_QuartzJob/Service/RouterService.cs
在类成员变量声明区之后、现有方法之前,新增以下私有方法:
/// <summary>
/// 从缓存获取指定类型的全量路由数据,缓存不存在时自动从数据库加载并写入缓存
/// </summary>
/// <param name="routeType">路由类型(入口/出口)</param>
/// <returns>该类型的全部路由列表</returns>
private List<Dt_Router> GetAllRoutersFromCache(int routeType)
{
string cacheKey = $"Router:AllRouters:{(routeType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}";
return _cacheService.GetOrAdd(
cacheKey,
() => BaseDal.QueryData(x => x.InOutType == routeType)
);
}
---
## Task 2: 改造 QueryNextRoutes 重载(2个方法)
**文件:**
- Modify: `WIDESEAWCS_QuartzJob/Service/RouterService.cs:48-98`
### QueryNextRoutes(string, string) — 第48-69行
原代码:
List allRouters = BaseDal.QueryData(x => true);
routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null);
```
改为:csharp List<Dt_Router> allRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); // 入口+出口都加载,FindRoutesInMemory 内部按 routeType==null 不做过滤 List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); allRouters.AddRange(outRouters); routers = FindRoutesInMemory(startPosi, endPosi, allRouters, null);
原代码:csharp List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType); routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType);
改为:csharp List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType); routers = FindRoutesInMemory(startPosi, endPosi, allRouters, routeType);
文件:
- Modify: WIDESEAWCS_QuartzJob/Service/RouterService.cs:189-314
原代码:csharp List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, ...); return routes.FirstOrDefault();
改为:csharp List<Dt_Router> routes = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()) .Where(x => x.StartPosi == startPosi) .ToList(); routes = routes.OrderByDescending(x => x.IsEnd).ToList(); return routes.FirstOrDefault();
原代码:csharp List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi && x.InOutType == routeType, ...); return routes.FirstOrDefault();
改为:csharp List<Dt_Router> routes = GetAllRoutersFromCache(routeType) .Where(x => x.StartPosi == startPosi) .ToList(); routes = routes.OrderByDescending(x => x.IsEnd).ToList(); return routes.FirstOrDefault();
原代码(第255行):csharp List<Dt_Router> allRouters = BaseDal.QueryData(x => x.InOutType == routeType);
改为:csharp List<Dt_Router> allRouters = GetAllRoutersFromCache(routeType);
其余直接路由判断和 FindRoutesInMemory 调用逻辑不变。
原代码(第285行):csharp List<Dt_Router> routes = BaseDal.QueryData(x => x.StartPosi == startPosi, ...);
改为(合并入口+出口两份缓存,与原方法全量查询语义一致):csharp List<Dt_Router> inRoutes = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); List<Dt_Router> outRoutes = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); List<Dt_Router> routes = inRoutes.Concat(outRoutes) .Where(x => x.StartPosi == startPosi) .ToList(); routes = routes.OrderByDescending(x => x.IsEnd).ToList();
然后复用已有的直接路由判断逻辑。
文件:
- Modify: WIDESEAWCS_QuartzJob/Service/RouterService.cs:323-366
第355行附近,原代码中 while 循环里每次调用 QueryNextRoute 的逻辑**不需要改动**(因为 QueryNextRoute 已经在 Task3 中改造了)。本任务的改动仅确认 QueryRoutePath 方法本身不再直接调用 BaseDal.QueryData,即不需要任何改动 —— 它调用的是 QueryNextRoute,而后者已被改造。
验证: 确认 QueryRoutePath 方法体内没有直接调用 BaseDal.QueryData,只有对 QueryNextRoute 的调用。
文件:
- Modify: WIDESEAWCS_QuartzJob/Service/RouterService.cs:412-446
原代码:csharp List<Dt_Router> allRouters = BaseDal.QueryData(x => true);
改为:csharp List<Dt_Router> inRouters = GetAllRoutersFromCache(RouterInOutType.In.ObjToInt()); List<Dt_Router> outRouters = GetAllRoutersFromCache(RouterInOutType.Out.ObjToInt()); List<Dt_Router> allRouters = inRouters.Concat(outRouters).ToList();
后续遍历 dt_Routers(取 IsEnd == true 的路由)的逻辑不变。
文件:
- Modify: WIDESEAWCS_QuartzJob/Service/RouterService.cs:511-594
在第568行附近,找到:csharp // 查询数据库中已有的路由信息 List<Dt_Router> dt_Routers = BaseDal.QueryData(x => x.InOutType == routerType);
这个 dt_Routers 是**添加之前**的已有数据,不包含本次新增的路由。在第586行 BaseDal.AddData(routers) 之后、content = WebResponseContent.Instance.OK() 之前,必须重新查询一次全量数据再写入缓存:
// 添加新的路由信息
BaseDal.AddData(routers);
// 重新查询全量路由(此时才包含新增的路由),再写入缓存
List<Dt_Router> updatedRouters = BaseDal.QueryData(x => x.InOutType == routerType);
string cacheKey = $"Router:AllRouters:{(routerType == RouterInOutType.In.ObjToInt() ? "In" : "Out")}";
_cacheService.Set(cacheKey, updatedRouters);
content = WebResponseContent.Instance.OK();
验证命令:bash dotnet build WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/WIDESEAWCS_QuartzJob.csproj
预期:无编译错误(CS0103/CS0019 等类型/语法错误全部修复后)
GetAllRoutersFromCache 私有方法QueryNextRoutes 两个重载QueryNextRoute 四个重载QueryRoutePath 无需改动(它依赖已改造的 QueryNextRoute)GetAllWholeRoutersAddRouters 更新缓存