330 lines
9.1 KiB
Markdown
330 lines
9.1 KiB
Markdown
# 定时任务执行范围修改说明
|
||
|
||
## 修改内容
|
||
|
||
### 修改目标
|
||
将定时任务 `ProcessPendingTasksAsync()` 的执行范围限制为仅处理创建时间在 **2026-05-10** 之后的订单。
|
||
|
||
### 修改日期
|
||
- **修改时间**: 2026-05-14
|
||
- **截断日期**: 2026-05-10 00:00:00
|
||
|
||
---
|
||
|
||
## 涉及文件修改
|
||
|
||
### 1. LabelReplaceRepository.cs
|
||
**文件路径**: `src/DAL/Repositories/LabelReplaceRepository.cs`
|
||
|
||
#### 修改的方法:
|
||
|
||
**1.1 GetNewOrdersWithLabelsAsync()**
|
||
```csharp
|
||
public async Task<List<string>> GetNewOrdersWithLabelsAsync(int limit)
|
||
{
|
||
var db = _provider.GetClient();
|
||
// 定义截断日期:2026-05-10之后
|
||
var cutoffDate = new DateTime(2026, 5, 10, 0, 0, 0);
|
||
|
||
return await db.Queryable<LabelReplaceEntity>()
|
||
.Where(o => !string.IsNullOrEmpty(o.Label))
|
||
.Where(o => o.CreatedAt >= cutoffDate) // 新增
|
||
.Where(o => !SqlFunc.Subqueryable<LabelPdfCache>()
|
||
.Where(c => c.NeutralWaybillNumber == o.NeutralWaybillNumber)
|
||
.Any())
|
||
.Select(o => o.NeutralWaybillNumber)
|
||
.Take(limit)
|
||
.ToListAsync();
|
||
}
|
||
```
|
||
|
||
**说明**:
|
||
- 添加了 `cutoffDate` 变量定义截断日期
|
||
- 添加了 `.Where(o => o.CreatedAt >= cutoffDate)` 条件过滤
|
||
- 该方法是定时任务获取新订单的主要入口
|
||
|
||
**1.2 GetAllOrdersWithLabelsAsync()**
|
||
```csharp
|
||
public async Task<List<LabelReplaceEntity>> GetAllOrdersWithLabelsAsync(int limit = 1000)
|
||
{
|
||
var db = _provider.GetClient();
|
||
var cutoffDate = new DateTime(2026, 5, 10, 0, 0, 0);
|
||
|
||
return await db.Queryable<LabelReplaceEntity>()
|
||
.Where(lr => !string.IsNullOrEmpty(lr.Label))
|
||
.Where(lr => lr.CreatedAt >= cutoffDate) // 新增
|
||
.Take(limit)
|
||
.ToListAsync();
|
||
}
|
||
```
|
||
|
||
**说明**:
|
||
- 添加了创建时间过滤条件
|
||
- 影响批量解析接口中 `mode=all` 的查询结果
|
||
|
||
**1.3 GetOrdersWithLabelsByDateRangeAsync()**
|
||
```csharp
|
||
public async Task<List<LabelReplaceEntity>> GetOrdersWithLabelsByDateRangeAsync(DateTime startDate, DateTime endDate, int limit = 1000)
|
||
{
|
||
var db = _provider.GetClient();
|
||
var cutoffDate = new DateTime(2026, 5, 10, 0, 0, 0);
|
||
|
||
// 确保指定的日期范围不低于截断日期
|
||
var finalStartDate = startDate < cutoffDate ? cutoffDate : startDate;
|
||
|
||
return await db.Queryable<LabelReplaceEntity>()
|
||
.Where(lr => !string.IsNullOrEmpty(lr.Label)
|
||
&& lr.CreatedAt >= finalStartDate // 修改
|
||
&& lr.CreatedAt <= endDate)
|
||
.Take(limit)
|
||
.ToListAsync();
|
||
}
|
||
```
|
||
|
||
**说明**:
|
||
- 添加了日期范围检查,确保开始日期不低于截断日期
|
||
- 影响批量解析接口中 `mode=range` 的查询结果
|
||
|
||
**1.4 GetOrdersWithLabelsByCustomerAsync()**
|
||
```csharp
|
||
public async Task<List<LabelReplaceEntity>> GetOrdersWithLabelsByCustomerAsync(int customerId, int limit = 1000)
|
||
{
|
||
var db = _provider.GetClient();
|
||
var cutoffDate = new DateTime(2026, 5, 10, 0, 0, 0);
|
||
|
||
return await db.Queryable<LabelReplaceEntity>()
|
||
.Where(lr => !string.IsNullOrEmpty(lr.Label)
|
||
&& lr.CustomerId == customerId
|
||
&& lr.CreatedAt >= cutoffDate) // 新增
|
||
.Take(limit)
|
||
.ToListAsync();
|
||
}
|
||
```
|
||
|
||
**说明**:
|
||
- 添加了创建时间过滤条件
|
||
- 影响批量解析接口中 `mode=customer` 的查询结果
|
||
|
||
---
|
||
|
||
## 工作流程影响
|
||
|
||
### 定时任务处理流程
|
||
|
||
定时任务执行时流程如下:
|
||
|
||
```
|
||
ProcessPendingTasksAsync()
|
||
├─ GetInvalidCachesAsync()
|
||
│ └─ 获取状态=3的无效缓存(结合订单表过滤)
|
||
│
|
||
├─ GetPendingTasksAsync()
|
||
│ └─ 获取状态=0和状态=2的待处理缓存
|
||
│
|
||
└─ GetNewOrdersWithLabelsAsync() ← 新增时间过滤
|
||
└─ 获取订单表中有标签但缓存表无记录的订单
|
||
└─ 过滤条件: CreatedAt >= 2026-05-10
|
||
```
|
||
|
||
### 受影响的查询
|
||
|
||
| 方法 | 影响 | 说明 |
|
||
|------|------|------|
|
||
| `GetNewOrdersWithLabelsAsync()` | ✅ 直接影响 | 定时任务的新订单获取方法 |
|
||
| `GetAllOrdersWithLabelsAsync()` | ✅ 直接影响 | 批量解析 `mode=all` |
|
||
| `GetOrdersWithLabelsByDateRangeAsync()` | ✅ 直接影响 | 批量解析 `mode=range` |
|
||
| `GetOrdersWithLabelsByCustomerAsync()` | ✅ 直接影响 | 批量解析 `mode=customer` |
|
||
|
||
---
|
||
|
||
## API 行为变化
|
||
|
||
### 批量解析接口 (`/batch-parse`)
|
||
|
||
**修改前**: 可以处理2026-05-10之前的订单
|
||
|
||
**修改后**: 只能处理2026-05-10及以后的订单
|
||
|
||
| 模式 | 说明 | 变化 |
|
||
|------|------|------|
|
||
| `all` | 处理所有有标签的订单 | ✅ 只处理>=2026-05-10的订单 |
|
||
| `range` | 按时间范围处理 | ✅ 开始日期自动调整至2026-05-10 |
|
||
| `customer` | 按客户处理 | ✅ 只处理>=2026-05-10的订单 |
|
||
| `single` | 单条订单处理 | ❌ 无变化(通过单号直接处理) |
|
||
|
||
### 示例
|
||
|
||
**请求 - 按时间范围处理**
|
||
```json
|
||
{
|
||
"mode": "range",
|
||
"startDate": "2026-05-01", // 实际从2026-05-10开始
|
||
"endDate": "2026-05-15"
|
||
}
|
||
```
|
||
|
||
**说明**: startDate 会被自动调整为 2026-05-10,因为这是截断日期
|
||
|
||
---
|
||
|
||
## 定时任务行为
|
||
|
||
### 定时任务的新特性
|
||
|
||
1. **自动时间过滤** - 所有查询都将受到创建时间的限制
|
||
2. **历史数据隔离** - 2026-05-10之前的订单不会被自动处理
|
||
3. **手动处理支持** - 通过 `mode=single` 可以手动处理任何订单
|
||
|
||
### 执行间隔
|
||
- **间隔**: 5分钟
|
||
- **处理范围**: 仅2026-05-10及以后的订单
|
||
- **批处理大小**: 100条(可配置)
|
||
|
||
---
|
||
|
||
## 配置参数
|
||
|
||
### 截断日期定义位置
|
||
|
||
所有截断日期都定义在数据访问层(Repository)中:
|
||
|
||
```csharp
|
||
var cutoffDate = new DateTime(2026, 5, 10, 0, 0, 0);
|
||
```
|
||
|
||
### 修改截断日期的方法
|
||
|
||
如需修改截断日期,只需更改上述时间值,例如改为2026-06-01:
|
||
|
||
```csharp
|
||
var cutoffDate = new DateTime(2026, 6, 1, 0, 0, 0);
|
||
```
|
||
|
||
然后重新编译和部署项目。
|
||
|
||
---
|
||
|
||
## 数据库影响
|
||
|
||
### 查询变化
|
||
|
||
**修改前SQL**:
|
||
```sql
|
||
SELECT o.NeutralWaybillNumber
|
||
FROM label_replace o
|
||
WHERE o.Label IS NOT NULL
|
||
AND NOT EXISTS (
|
||
SELECT 1 FROM label_pdf_cache c
|
||
WHERE c.NeutralWaybillNumber = o.NeutralWaybillNumber
|
||
)
|
||
LIMIT 100;
|
||
```
|
||
|
||
**修改后SQL**:
|
||
```sql
|
||
SELECT o.NeutralWaybillNumber
|
||
FROM label_replace o
|
||
WHERE o.Label IS NOT NULL
|
||
AND o.CreatedAt >= '2026-05-10' -- 新增条件
|
||
AND NOT EXISTS (
|
||
SELECT 1 FROM label_pdf_cache c
|
||
WHERE c.NeutralWaybillNumber = o.NeutralWaybillNumber
|
||
)
|
||
LIMIT 100;
|
||
```
|
||
|
||
### 性能考虑
|
||
|
||
- 添加的 `CreatedAt >= cutoffDate` 条件可以利用现有的时间索引
|
||
- 预期查询性能无负面影响
|
||
- 可能会减少返回结果数量(因为过滤了旧数据)
|
||
|
||
---
|
||
|
||
## 兼容性
|
||
|
||
### 向后兼容性
|
||
- ✅ 单条处理模式 (`mode=single`) 不受影响
|
||
- ❌ 通过API手动处理时会受到时间限制
|
||
|
||
### 版本信息
|
||
- **修改版本**: v2.1
|
||
- **兼容版本**: v2.0(如需处理旧数据,需升级到v2.1后手动处理)
|
||
|
||
---
|
||
|
||
## 测试验证
|
||
|
||
### 编译验证
|
||
✅ 整个项目已成功编译,无新的编译错误
|
||
|
||
### 功能验证清单
|
||
|
||
- [ ] 定时任务成功运行(每5分钟一次)
|
||
- [ ] 只处理2026-05-10之后的订单
|
||
- [ ] 2026-05-10之前的订单不被处理
|
||
- [ ] 批量解析接口在 `mode=all` 时只返回新数据
|
||
- [ ] 批量解析接口在 `mode=range` 时正确调整日期范围
|
||
- [ ] 批量解析接口在 `mode=customer` 时只返回新客户订单
|
||
- [ ] 缓存统计接口统计正确
|
||
|
||
### 手动测试命令
|
||
|
||
```bash
|
||
# 测试批量解析 - all模式
|
||
curl -X POST http://localhost:5002/api/label/batch-parse \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"mode":"all","limit":10}'
|
||
|
||
# 测试批量解析 - range模式(时间范围自动调整)
|
||
curl -X POST http://localhost:5002/api/label/batch-parse \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"mode":"range","startDate":"2026-05-01","endDate":"2026-05-15","limit":10}'
|
||
|
||
# 测试定时任务状态
|
||
curl -X GET http://localhost:5002/api/label/background-service/status
|
||
```
|
||
|
||
---
|
||
|
||
## 回滚方案
|
||
|
||
如需恢复到修改前的行为,只需:
|
||
|
||
1. 移除所有的 `var cutoffDate = new DateTime(2026, 5, 10, 0, 0, 0);` 定义
|
||
2. 移除所有的 `.Where(lr => lr.CreatedAt >= cutoffDate)` 条件
|
||
3. 重新编译和部署
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
### Q: 如何处理2026-05-10之前的订单?
|
||
A: 使用 `mode=single` 通过单号进行手动处理:
|
||
```json
|
||
{"mode":"single","waybillNumber":"1Z999AA10123456784"}
|
||
```
|
||
|
||
### Q: 定时任务会处理旧订单吗?
|
||
A: 不会。定时任务 (`GetNewOrdersWithLabelsAsync`) 已被限制为仅处理2026-05-10及以后的订单。
|
||
|
||
### Q: 缓存统计会包含旧数据吗?
|
||
A: 是的。`cache-statistics` 接口统计的是缓存表中的所有数据,不受时间限制。
|
||
|
||
### Q: 如何修改截断日期?
|
||
A: 修改所有Repository中的 `new DateTime(2026, 5, 10, 0, 0, 0)` 为新的日期,然后重新编译部署。
|
||
|
||
---
|
||
|
||
## 相关文件
|
||
|
||
- **修改的数据库访问类**: `src/DAL/Repositories/LabelReplaceRepository.cs`
|
||
- **定时任务类**: `src/BLL/Services/LabelPdfCacheService.cs`
|
||
- **批量解析接口**: `src/CONTROLLER/Controllers/LabelController.cs`
|
||
|
||
---
|
||
|
||
**修改完成于**: 2026-05-14
|
||
**编译状态**: ✅ 成功
|
||
**部署状态**: 等待确认
|