# 定时任务暂停指南

## 概述

项目中的PDF标签缓存定时任务是通过 `LabelPdfCacheBackgroundService` 实现的，它是一个 ASP.NET Core `BackgroundService`，每5分钟执行一次。

---

## 定时任务信息

### 基本参数
- **服务类**: `LabelPdfCacheBackgroundService`
- **执行间隔**: 5分钟
- **功能**: 处理待处理的PDF缓存任务
- **执行方法**: `ProcessPendingTasksAsync()`

### 当前工作流程
1. 每5分钟检查一次待处理任务
2. 获取失效的缓存、未处理的任务、新订单
3. 批量处理这些任务
4. 同步保存PDF缓存，异步识别条码

---

## 暂停定时任务的方法

### 方法1：修改配置文件（推荐用于生产环境）

#### 步骤1：修改 appsettings.json

在 `appsettings.json` 或 `appsettings.Production.json` 中添加一个配置开关：

```json
{
  "BackgroundServices": {
    "LabelPdfCacheServiceEnabled": false
  }
}
```

#### 步骤2：修改 Program.cs

修改Program.cs中的注册代码：

```csharp
// 从这样：
builder.Services.AddHostedService<CONTROLLER.BackgroundServices.LabelPdfCacheBackgroundService>();

// 改为：
var enableLabelPdfCache = builder.Configuration.GetValue<bool>("BackgroundServices:LabelPdfCacheServiceEnabled", true);
if (enableLabelPdfCache)
{
    builder.Services.AddHostedService<CONTROLLER.BackgroundServices.LabelPdfCacheBackgroundService>();
}
```

#### 优点
- 无需重新编译代码
- 支持配置热更新
- 适合生产环境

#### 缺点
- 需要修改两个文件
- 需要重启应用

---

### 方法2：使用环境变量

#### 步骤1：修改 Program.cs

```csharp
var enableLabelPdfCache = 
    !string.Equals(
        Environment.GetEnvironmentVariable("DISABLE_LABEL_PDF_CACHE"), 
        "true", 
        StringComparison.OrdinalIgnoreCase);

if (enableLabelPdfCache)
{
    builder.Services.AddHostedService<CONTROLLER.BackgroundServices.LabelPdfCacheBackgroundService>();
}
```

#### 步骤2：设置环境变量

**Windows命令行：**
```bash
set DISABLE_LABEL_PDF_CACHE=true
```

**Linux/Mac：**
```bash
export DISABLE_LABEL_PDF_CACHE=true
```

**Docker：**
```dockerfile
ENV DISABLE_LABEL_PDF_CACHE=true
```

#### 优点
- 不需要修改配置文件
- 容易在Docker容器中配置
- 支持运行时切换

#### 缺点
- 需要修改代码
- 需要重启应用

---

### 方法3：创建暂停/恢复接口（最灵活）

#### 优点
- 可以在运行时动态控制
- 无需重启应用
- 最灵活，适合生产环境

#### 缺点
- 需要修改更多代码
- 状态只在内存中保存，重启后会重置

---

## 方法对比

| 方法 | 修改代码 | 重启应用 | 实时性 | 推荐场景 |
|------|--------|--------|-------|---------|
| 方法1：配置文件 | 中等 | 是 | 低 | 生产环境固定配置 |
| 方法2：环境变量 | 中等 | 是 | 低 | Docker容器部署 |
| 方法3：管理接口 | 高 | 否 | 高 | 需要灵活控制 |

---

## 使用方法3的API调用示例

### JavaScript/Fetch
```javascript
// 暂停定时任务
async function pauseBackgroundService() {
  const response = await fetch('http://localhost:5002/api/label/background-service/pause', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    }
  });
  const data = await response.json();
  console.log(data);
}

// 恢复定时任务
async function resumeBackgroundService() {
  const response = await fetch('http://localhost:5002/api/label/background-service/resume', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    }
  });
  const data = await response.json();
  console.log(data);
}

// 获取定时任务状态
async function getBackgroundServiceStatus() {
  const response = await fetch('http://localhost:5002/api/label/background-service/status');
  const data = await response.json();
  console.log(data);
}
```

### Python
```python
import requests

BASE_URL = "http://localhost:5002/api/label"

# 暂停定时任务
def pause_service():
    response = requests.post(f"{BASE_URL}/background-service/pause")
    print(response.json())

# 恢复定时任务
def resume_service():
    response = requests.post(f"{BASE_URL}/background-service/resume")
    print(response.json())

# 获取定时任务状态
def get_status():
    response = requests.get(f"{BASE_URL}/background-service/status")
    print(response.json())
```

### cURL
```bash
# 暂停定时任务
curl -X POST http://localhost:5002/api/label/background-service/pause

# 恢复定时任务
curl -X POST http://localhost:5002/api/label/background-service/resume

# 获取定时任务状态
curl -X GET http://localhost:5002/api/label/background-service/status
```

---

## 预期响应

### 成功暂停
```json
{
  "status": "success",
  "message": "后台定时任务已暂停",
  "data": {
    "isRunning": false
  }
}
```

### 成功恢复
```json
{
  "status": "success",
  "message": "后台定时任务已恢复",
  "data": {
    "isRunning": true
  }
}
```

### 获取状态
```json
{
  "status": "success",
  "message": "获取后台服务状态成功",
  "data": {
    "isRunning": true,
    "service": "LabelPdfCacheBackgroundService",
    "interval": "5 minutes"
  }
}
```

---

## 注意事项

1. **数据不会丢失** - 暂停定时任务只是停止周期性执行，已有的待处理任务不会被删除

2. **可以手动处理** - 暂停后可以通过 `/batch-parse` 接口手动触发处理

3. **性能考虑** - 长时间暂停可能导致待处理任务堆积

4. **内存状态** - 如果使用方法3，重启应用后服务会自动恢复运行

5. **监控建议** - 建议定期检查任务状态，确保没有任务堆积

---

## 常见场景

### 场景1：维护期间暂停
如需进行数据库维护或其他重要操作，可以暂停定时任务避免并发冲突：

```bash
# 暂停
curl -X POST http://localhost:5002/api/label/background-service/pause

# 执行维护操作
# ...

# 恢复
curl -X POST http://localhost:5002/api/label/background-service/resume
```

### 场景2：定点手动处理
暂停自动定时任务，改为手动通过API按需处理：

```bash
# 暂停自动任务
curl -X POST http://localhost:5002/api/label/background-service/pause

# 手动触发解析（当需要时）
curl -X POST http://localhost:5002/api/label/batch-parse \
  -H "Content-Type: application/json" \
  -d '{"mode":"all","limit":500}'
```

### 场景3：监控异常时暂停
如发现定时任务出现异常，可以快速暂停避免继续出错：

```bash
# 检查状态
curl -X GET http://localhost:5002/api/label/background-service/status

# 如果出现异常，暂停
curl -X POST http://localhost:5002/api/label/background-service/pause

# 调查问题后恢复
curl -X POST http://localhost:5002/api/label/background-service/resume
```

---

## 故障排查

### Q: 暂停后定时任务仍在执行
**A:** 可能使用的是方法1或方法2，需要重启应用才能生效

### Q: 暂停状态在重启后丢失
**A:** 这是正常的。如需持久化暂停状态，可以将状态保存到数据库

### Q: 恢复后任务堆积
**A:** 这是正常的。系统会逐个处理堆积的任务。可以调整 `ProcessPendingTasksAsync()` 的批处理大小来优化处理速度

---

## 推荐实施方案

根据部署环境选择：

- **开发环境**: 使用方法3（API接口），方便调试
- **生产环境单机**: 使用方法1（配置文件），稳定可靠
- **生产环境Docker**: 使用方法2（环境变量），配置灵活
- **生产环境微服务**: 使用方法3（API接口），需要分布式协调

---

## 参考信息

- **定时任务执行间隔**: 5分钟（见 `LabelPdfCacheBackgroundService.cs` 第18行）
- **处理方法**: `ProcessPendingTasksAsync()` 
- **处理范围**: 失效缓存、待处理任务、新订单
- **错误处理**: 自动捕获异常，记录日志
