# VAT异步任务队列处理器 - 实现总结

## 修改概述

已成功重构 `task/queue_processor.php`，实现从 **拉取模式** 到 **推送模式** 的转变。

## 核心改动

### 1. 工作流程变更

**原流程：**
```
从 task 表读取任务 ID
    ↓
根据 ID 查询 VAT 表数据
    ↓
执行文档生成
    ↓
更新任务状态
```

**新流程：**
```
直接查询 VAT 表（PushTaxBureauStatus = 5）
    ↓
检查是否已有对应任务记录
    ↓
如果没有，创建新任务
    ↓
执行文档生成
    ↓
文件生成成功后，更新 PushTaxBureauStatus = 6
    ↓
更新任务状态
```

### 2. 新增函数

#### `getPendingVATRecords()`
- **功能：** 通过 EPRBusinessRecord JOIN EPRRegInfo 查询待处理数据（PushTaxBureauStatus已迁移到EPRRegInfo）
- **查询条件：**
  - Country = 'ES'
  - PushTaxBureauStatus = 5
  - 不存在处于 0、1、2 状态的任务记录
- **返回：** 待处理VAT记录数组

#### `createOrGetTask()`
- **功能：** 创建或获取任务记录
- **逻辑：**
  1. 检查是否已存在任务
  2. 存在则返回现有ID
  3. 不存在则创建新任务
- **返回：** 任务ID

#### `updatePushStatus()`
- **功能：** 更新 EPRRegInfo 表的 PushTaxBureauStatus 和 Remarks
- **更新字段：**
  - `PushTaxBureauStatus`：任务完成状态
  - `Remarks`：错误消息（失败时）
- **执行时机：** 文件生成失败后设为 7，成功后设为 6

### 3. 代码结构改动

**主循环中的关键变化：**

```php
// 旧方式
$pendingTasks = $taskManager->getPendingTasks($maxTasks);
foreach ($pendingTasks as $task) {
    $taskId = $task['Id'];
    $vatId = $task['EPRBusinessRecordId'];
    // 处理...
}

// 新方式
$pendingVATRecords = getPendingVATRecords($dataService, $taskManager, $maxTasks, $logger);
foreach ($pendingVATRecords as $vatRecord) {
    $vatId = $vatRecord['ID'];
    $taskId = createOrGetTask($taskManager, $vatId, $vatRecord, $logger);
    // 处理...
    updatePushDates($taskManager, $vatId, $logger);
}
```

### 4. 依赖关系

**新增导入：**
```php
use Haiya\VATDataService;
```

**使用的现有类：**
- `AsyncTaskManager`：任务管理
- `VATAsyncProcessor`：文档生成
- `Logger`：日志记录
- `TempFileCleanupManager`：临时文件清理

## 数据库变更

### 必需字段

**EPRRegInfo 表（PushTaxBureauStatus已从EPRBusinessRecord迁移至此）：**
- `PushTaxBureauStatus` (INT)：推送状态（5=待处理）
- `Remarks` (NVARCHAR)：错误消息/备注

### 推荐索引

```sql
-- 提高查询性能
CREATE INDEX IX_EPRRegInfo_Country_Status
ON EPRRegInfo(Country, PushTaxBureauStatus)
WHERE Country = 'ES' AND PushTaxBureauStatus = 5;

CREATE INDEX IX_EPRHaiyaProcessingTasks_VATId_Status 
ON EPRHaiyaProcessingTasks(EPRBusinessRecordId, Status);
```

## 功能特性

### 1. 自动任务创建
- 无需预先在 task 表中创建任务
- 处理器自动检测并创建缺失的任务

### 2. 智能重试机制
- 基于 task 表的记录数判断重试次数
- 失败自动重试，达到上限后标记为失败

### 3. 推送日期管理
- `PushTaxBureauDate`：首次推送日期（不再更新）
- `PushApiDate`：最新推送日期（每次更新）

### 4. 数据库连接保活
- 每5分钟执行一次 `SELECT 1` 查询
- 防止长时间无操作导致连接断开

### 5. 内存监控
- 每60秒输出心跳日志
- 内存超过800MB时记录警告

## 日志改进

### 新增日志信息

```
[时间] 查询待处理VAT记录 - count: X
[时间] 开始处理VAT记录 - vat_id: X
[时间] 任务已存在 - vat_id: X, task_id: Y
[时间] 创建新任务 - vat_id: X, task_id: Y
[时间] 更新推送日期成功 - vat_id: X, push_date: YYYY-MM-DD
```

### 日志位置
```
logs/queue_processor_YYYYMMDD.log
```

## 配置参数

```bash
php task/queue_processor.php [选项]

选项：
  --interval=30     检查间隔（秒），默认8秒
  --max-tasks=5     每次最多处理的任务数，默认1个
  --daemon          以守护进程模式运行
  --help            显示帮助信息
```

## 性能影响

### 优势
- ✅ 减少数据库查询（直接查VAT表）
- ✅ 避免数据不一致（单一数据源）
- ✅ 自动处理缺失任务
- ✅ 更清晰的处理流程

### 考虑因素
- 需要确保 EPRRegInfo 表有 PushTaxBureauStatus 字段
- 需要创建推荐的索引以提高性能
- 首次运行时可能需要创建大量任务记录

## 迁移步骤

### 1. 数据库准备
```bash
# 执行数据库schema脚本
sqlcmd -S <server> -d <database> -i database/EPRHaiyaProcessingTasks.sql
```

### 2. 代码部署
```bash
# 替换 task/queue_processor.php
cp task/queue_processor.php task/queue_processor.php.backup
# 部署新版本
```

### 3. 启动处理器
```bash
# 测试模式
php task/queue_processor.php

# 生产模式
php task/queue_processor.php --daemon
```

### 4. 监控验证
```bash
# 查看日志
tail -f logs/queue_processor_*.log

# 验证推送日期是否更新
SELECT ID, PushTaxBureauDate, PushApiDate
FROM EPRRegInfo
WHERE Country = 'ES' AND PushTaxBureauStatus = 5
```

## 文档清单

| 文件 | 说明 |
|------|------|
| `docs/QUICK_REFERENCE.md` | 常用命令速查表 |
| `docs/QUEUE_PROCESSOR_README.md` | 完整使用指南 |
| `docs/IMPLEMENTATION_SUMMARY.md` | 本文件 - 实现总结 |

## 故障排查

### 问题：没有找到待处理记录
**解决：** 检查 EPRRegInfo 表中是否有 `PushTaxBureauStatus = 5` 的记录（注意：该字段已从 EPRBusinessRecord 迁移到 EPRRegInfo）

### 问题：任务创建失败
**解决：** 检查 EPRHaiyaProcessingTasks 表权限和外键约束

### 问题：推送日期未更新
**解决：** 确认文件生成成功且任务状态为 COMPLETED

### 问题：处理器内存持续增长
**解决：** 检查日志中的内存警告，可能需要增加服务器内存或调整参数

## 后续优化建议

1. **性能优化**
   - 根据实际情况调整 `--interval` 和 `--max-tasks` 参数
   - 定期清理过期的任务记录

2. **监控增强**
   - 集成到监控系统（如 Prometheus）
   - 设置告警规则

3. **功能扩展**
   - 支持其他国家代码（不仅限于 'ES'）
   - 支持批量重试失败的任务

4. **代码改进**
   - 将辅助函数移到独立的类中
   - 增加单元测试覆盖

## 版本信息

- **PHP版本：** 8.3.25
- **修改日期：** 2026-03-19
- **修改类型：** 工作流程重构
- **向后兼容性：** 否（需要数据库迁移）

## 相关文件

- `task/queue_processor.php` - 主处理器（已修改）
- `src/AsyncTaskManager.php` - 任务管理（无修改）
- `src/VATAsyncProcessor.php` - 文档生成（文件生成成功后设 PushTaxBureauStatus = 6，失败设 7）
- `src/VATDataService.php` - 数据服务（无修改）
- `src/Logger.php` - 日志记录（无修改）
