5.9 KiB
5.9 KiB
定时任务执行范围优化 - 总结
日期: 2026-05-13
状态: ✅ 完成并编译通过
🎯 问题分析
定时任务应该处理订单表中有标签的数据,但之前的实现只处理:
- ❌ 缓存表中status=0(待处理)的记录
- ❌ 缓存表中status=2(失败)且未超过重试次数的记录
漏洞:订单表中新增的有标签订单如果不在缓存表中,就永远不会被处理。
✅ 改进方案
现在定时任务按以下优先级处理:
第一步:处理失效的缓存(Status=3)
└─ 订单表中有对应的有标签订单
第二步:处理待处理的任务(Status=0或2)
└─ 订单表中有对应的有标签订单
第三步:处理订单表中新的有标签订单 ⭐ 新增
└─ 缓存表中不存在对应记录
└─ 订单表中该订单有标签数据
🔧 代码修改
1. 新增Repository方法
文件: LabelPdfCacheRepository.cs
/// <summary>
/// 获取订单表中新的有标签订单(缓存表中不存在的)
/// </summary>
public async Task<List<string>> GetNewOrdersWithLabelsAsync(int limit)
{
var db = _provider.GetClient();
return await db.Queryable<LabelReplaceEntity>()
.Where(o => !string.IsNullOrEmpty(o.Label)) // 订单有标签
.Where(o => !SqlFunc.Subqueryable<LabelPdfCache>()
.Where(c => c.NeutralWaybillNumber == o.NeutralWaybillNumber)
.Any()) // 缓存表中不存在
.Select(o => o.NeutralWaybillNumber)
.Take(limit)
.ToListAsync();
}
关键SQL逻辑:
SELECT o.NeutralWaybillNumber
FROM LabelReplaceEntity o
WHERE o.Label IS NOT NULL AND o.Label != ''
AND NOT EXISTS (
SELECT 1 FROM label_pdf_cache c
WHERE c.NeutralWaybillNumber = o.NeutralWaybillNumber
)
2. 更新接口定义
文件: ILabelPdfCacheRepository.cs
- 添加
GetNewOrdersWithLabelsAsync方法签名
3. 增强ProcessPendingTasksAsync逻辑
文件: LabelPdfCacheService.cs
新增第三步处理流程:
// 第三步:处理订单表中新的有标签订单
var newBatchSize = remainingBatchSize - pendingTasks.Count;
if (newBatchSize > 0)
{
var newOrders = await _cacheRepository.GetNewOrdersWithLabelsAsync(newBatchSize);
foreach (var waybillNumber in newOrders)
{
if (await ProcessSingleCacheTask(waybillNumber))
{
successCount++;
}
}
}
改进的日志:
Completed processing PDF cache tasks,
total processed: 45,
invalid: 5,
pending: 15,
new orders: 25
📊 执行范围对比
修改前 ❌
| 订单状态 | 处理范围 |
|---|---|
| 订单有标签 | ❌ 仅处理缓存表中已存在的 |
| 新订单有标签 | ❌ 永远不会处理 |
| 缓存表无记录 | ❌ 跳过 |
修改后 ✅
| 订单状态 | 处理范围 |
|---|---|
| 失效缓存有标签 | ✅ 第一步处理 |
| 待处理缓存有标签 | ✅ 第二步处理 |
| 新订单有标签 | ✅ 第三步处理 |
| 缓存表无记录 | ✅ 新增处理 |
💡 工作流程示例
场景:早上10:00定时任务执行,batchSize=100
【第一步】处理失效缓存
查询:SELECT * FROM label_pdf_cache WHERE Status=3 AND OrderWithLabel LIMIT 100
结果:找到5条失效缓存
操作:重新处理这5条
【第二步】处理待处理任务
查询:SELECT * FROM label_pdf_cache
WHERE (Status=0 OR (Status=2 AND RetryCount<3))
AND OrderWithLabel LIMIT 95
结果:找到15条待处理
操作:继续处理这15条
【第三步】处理新订单 ⭐ 新增
查询:SELECT o.NeutralWaybillNumber FROM LabelReplaceEntity o
WHERE o.Label IS NOT NULL
AND NOT EXISTS (SELECT 1 FROM label_pdf_cache c
WHERE c.NeutralWaybillNumber = o.NeutralWaybillNumber)
LIMIT 80
结果:找到25条新订单有标签
操作:为这25条新订单创建缓存
【结果】
本次执行处理了 45 条记录
- 失效缓存:5条
- 待处理任务:15条
- 新订单:25条
🛡️ 防护机制
-
订单标签有效性检查
.Where(o => !string.IsNullOrEmpty(o.Label)) // 确保Label不为空 -
重复处理防护
.Where(o => !SqlFunc.Subqueryable<LabelPdfCache>() .Where(c => c.NeutralWaybillNumber == o.NeutralWaybillNumber) .Any()) // 确保缓存表中不存在 -
批量处理限制
- batchSize控制单次处理数量
- 防止定时任务过度执行
-
完整的日志记录
- 记录各阶段处理数量
- 便于监控和调试
✨ 现在的覆盖场景
| 场景 | 处理方式 | 结果 |
|---|---|---|
| 新订单有标签 | 第三步 | ✅ 立即创建缓存 |
| 已缓存订单 | 第一、二步 | ✅ 重试或更新 |
| 订单无标签 | 过滤掉 | ✅ 跳过 |
| 缓存表无记录 | 第三步 | ✅ 创建新记录 |
📈 预期收益
-
完整覆盖 ✅
- 不再有漏掉的新订单
- 所有有标签订单都会被处理
-
及时处理 ✅
- 新订单会在下个定时任务周期处理
- 缩短缓存生成时间
-
可观测性 ✅
- 详细的执行日志
- 清晰的处理数量统计
-
性能平衡 ✅
- batchSize限制单次处理量
- 不会过度消耗资源
📝 编译验证
✅ 编译成功(exit code = 0)
✅ 零编译错误
✅ 新增方法已实现
✅ 接口已更新
✅ 逻辑已完善
🚀 现在的定时任务能够
- ✅ 处理订单表中所有有标签的订单
- ✅ 优先处理失效和待处理的缓存
- ✅ 自动发现新的有标签订单
- ✅ 为新订单创建缓存记录
- ✅ 提供详细的执行日志
任务完成!定时任务现在能够正确处理订单表中所有有标签的数据。 ✅