Files
LabelChange-server/.trae/docs/BackgroundTasks/06-源代码参考.md
2026-06-01 16:30:29 +08:00

285 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 定时任务源代码参考
## 文件位置总览
### 后台服务相关
#### 1. LabelPdfCacheBackgroundService.cs
**路径**: `src/CONTROLLER/BackgroundServices/LabelPdfCacheBackgroundService.cs`
**作用**: 定时任务的主服务类
**关键内容**:
- `ExecuteAsync()` - 后台服务的主方法每5分钟执行一次
- `TaskIntervalMinutes = 5` - 执行间隔设置
- 依赖注入了 `ILabelPdfCacheService`
**示例代码位置**:
- 第18行: 执行间隔定义
- 第25-40行: 构造函数和依赖注入
- 第42-70行: ExecuteAsync主方法实现
#### 2. BackgroundServiceManager.cs
**路径**: `src/CONTROLLER/BackgroundServices/BackgroundServiceManager.cs`
**作用**: 管理后台服务的暂停/恢复
**关键内容**:
- `PauseService()` - 暂停服务
- `ResumeService()` - 恢复服务
- `IsRunning()` - 检查运行状态
- `GetCancellationToken()` - 获取取消令牌
---
### 业务逻辑相关
#### 3. LabelPdfCacheService.cs
**路径**: `src/BLL/Services/LabelPdfCacheService.cs`
**作用**: PDF缓存的业务逻辑处理
**关键方法**:
- `ProcessPendingTasksAsync()` (第235-290行)
- 处理失效缓存
- 处理待处理任务
- 处理新订单(仅>=2026-05-10
- `ProcessSingleCacheTaskAsync()` (第291-350行)
- 处理单个订单
- 获取PDF字节流
- 同步保存缓存
- 异步识别条码
- `RecognizeBarcodeAsync()` (第450-550行)
- 条码识别逻辑
- 支持一维码和二维码
- `GetCacheStatisticsAsync()` (第580-620行)
- 获取统计信息
#### 4. LabelPdfCacheBackgroundService.cs 中的调用
**关键代码位置**: 第50-65行
```csharp
var successCount = await cacheService.ProcessPendingTasksAsync();
```
---
### 数据访问相关
#### 5. LabelPdfCacheRepository.cs
**路径**: `src/DAL/Repositories/LabelPdfCacheRepository.cs`
**关键方法**:
1. **GetNewOrdersWithLabelsAsync()** (第142-152行)
- 获取新订单(无时间限制)
- 用于 batch-parse 接口
2. **GetNewOrdersWithLabelsForBackgroundTaskAsync()** (第183-200行)
- 获取新订单(仅>=2026-05-10
- **仅用于定时任务**
- 关键代码位置: 第186行
```csharp
var cutoffDate = new DateTime(2026, 5, 10, 0, 0, 0);
```
3. **GetInvalidCachesAsync()** (第53-65行)
- 获取失效缓存
4. **GetPendingTasksAsync()** (第67-85行)
- 获取待处理任务
---
### 接口/API相关
#### 6. LabelController.cs
**路径**: `src/CONTROLLER/Controllers/LabelController.cs`
**定时任务相关接口**:
1. **batch-parse** (第2510-2640行)
- POST `/api/label/batch-parse`
- 支持4种模式: all, range, customer, single
- 不受时间限制
2. **cache-statistics** (第2652-2670行)
- GET `/api/label/cache-statistics`
- 获取缓存统计信息
3. **background-service/pause** (需要实现)
- POST `/api/label/background-service/pause`
- 暂停定时任务
4. **background-service/resume** (需要实现)
- POST `/api/label/background-service/resume`
- 恢复定时任务
5. **background-service/status** (需要实现)
- GET `/api/label/background-service/status`
- 查看定时任务状态
---
## 关键代码片段
### 定时任务执行流程
**文件**: `LabelPdfCacheService.cs` 第235-290行
```csharp
public async Task<int> ProcessPendingTasksAsync(int maxRetryCount = 3, int batchSize = 100)
{
var successCount = 0;
try
{
// 第一步:处理失效的缓存
var invalidCaches = await _cacheRepository.GetInvalidCachesAsync(batchSize);
// 第二步:处理待处理的任务
var remainingBatchSize = batchSize - invalidCaches.Count;
var pendingTasks = await _cacheRepository.GetPendingTasksAsync(maxRetryCount, remainingBatchSize);
// 第三步:处理订单表中新的有标签订单(仅>=2026-05-10
var newBatchSize = remainingBatchSize - pendingTasks.Count;
if (newBatchSize > 0)
{
// 使用专用方法获取新订单(受时间限制)
var newOrders = await _cacheRepository.GetNewOrdersWithLabelsForBackgroundTaskAsync(newBatchSize);
foreach (var waybillNumber in newOrders)
{
if (await ProcessSingleCacheTask(waybillNumber))
{
successCount++;
}
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in ProcessPendingTasksAsync");
}
return successCount;
}
```
### 定时任务新订单查询(受时间限制)
**文件**: `LabelPdfCacheRepository.cs` 第183-200行
```csharp
public async Task<List<string>> GetNewOrdersWithLabelsForBackgroundTaskAsync(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();
}
```
### 通用新订单查询(无时间限制)
**文件**: `LabelPdfCacheRepository.cs` 第142-152行
```csharp
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();
}
```
---
## 配置参数修改位置
### 1. 执行间隔 (5分钟)
**文件**: `LabelPdfCacheBackgroundService.cs` 第18行
```csharp
private const int TaskIntervalMinutes = 5;
```
**改为**: 所需的分钟数
### 2. 批处理大小 (100条)
**文件**: `LabelPdfCacheService.cs` ProcessPendingTasksAsync方法参数
```csharp
public async Task<int> ProcessPendingTasksAsync(int maxRetryCount = 3, int batchSize = 100)
```
**改为**: 所需的批处理大小
### 3. 重试次数 (3次)
**文件**: `LabelPdfCacheService.cs` ProcessPendingTasksAsync方法参数
```csharp
public async Task<int> ProcessPendingTasksAsync(int maxRetryCount = 3, int batchSize = 100)
```
**改为**: 所需的重试次数
### 4. 时间限制日期 (2026-05-10)
**文件**: `LabelPdfCacheRepository.cs` GetNewOrdersWithLabelsForBackgroundTaskAsync方法
```csharp
var cutoffDate = new DateTime(2026, 5, 10, 0, 0, 0);
```
**改为**: 所需的日期
---
## 依赖关系
```
LabelPdfCacheBackgroundService
└─→ ILabelPdfCacheService
├─→ ILabelPdfCacheRepository
│ ↓
│ └─→ SqlSugar (数据库)
└─→ ILogger
```
---
## 调试技巧
### 打断点位置
1. **定时任务执行**: `LabelPdfCacheBackgroundService.ExecuteAsync()`
2. **处理逻辑**: `LabelPdfCacheService.ProcessPendingTasksAsync()`
3. **单个订单处理**: `LabelPdfCacheService.ProcessSingleCacheTaskAsync()`
4. **查询新订单**: `LabelPdfCacheRepository.GetNewOrdersWithLabelsForBackgroundTaskAsync()`
### 查看日志
日志文件位置: `logs/` 目录
关键日志关键字:
- "Label PDF Cache Background Service is starting"
- "Starting label PDF cache processing task"
- "Completed label PDF cache processing task"
- "Error occurred in label PDF cache background service"
---
**最后更新**: 2026-05-14