# 任务与指令的区别说明

## 📋 概述

在调度系统中，**任务（Task）** 和 **指令（Command）** 是两个不同层次的概念，它们的关系是：**一个任务可以包含多个指令**。

### ⚠️ 重要说明

**当前系统实际情况**：
- **真正的任务**：目前只有 `auto_deliver`（自动投递任务）是真正的任务，它包含多个步骤和指令
- **伪任务**：虽然代码中有 `get_resume`、`get_job_list`、`send_chat`、`apply_job` 等任务处理器，但它们实际上只是包装了单个指令，本质上就是直接执行指令

**为什么会有伪任务**：
1. 统一的任务追踪和日志记录
2. 保持接口的一致性
3. 未来可能扩展为真正的任务（包含多个步骤）

## 🔄 层级关系

```
任务（Task）
  ├── 指令1（Command）
  ├── 指令2（Command）
  └── 指令3（Command）
```

## 📊 详细对比

| 维度 | 任务（Task） | 指令（Command） |
|------|------------|----------------|
| **概念层级** | 业务层 | 执行层 |
| **数据库表** | `task_status` | `task_commands` |
| **管理模块** | TaskQueue（任务队列） | CommandManager（指令管理器） |
| **处理模块** | TaskHandlers（任务处理器） | jobManager（业务管理器） |
| **粒度** | 粗粒度（业务流程） | 细粒度（具体操作） |
| **包含关系** | 包含多个指令 | 属于某个任务 |
| **执行方式** | 由任务队列调度 | 由指令管理器执行 |
| **通信方式** | 内部调度 | 通过 MQTT 发送到客户端 |

## 🎯 任务（Task）

### 定义
任务是业务层面的概念，代表一个完整的业务流程或工作单元。

### 特点
- **业务导向**：代表一个完整的业务目标
- **可包含多个步骤**：一个任务可以包含多个指令
- **有生命周期**：pending → running → completed/failed
- **有优先级**：可以设置任务优先级
- **有超时机制**：任务级别有超时保护

### 任务类型示例

**真正的任务（包含多个步骤）**：
- `auto_deliver` - 自动投递任务（包含多个子操作：获取简历、获取岗位列表、筛选职位、批量投递）
- `auto_chat` - 自动沟通任务（待实现：自动与HR进行沟通，回复消息等）
- `auto_active_account` - 自动活跃账号任务（待实现：自动执行操作保持账号活跃度）

**注意**：目前系统中只有 `auto_deliver` 是已实现的真正任务，`auto_chat` 和 `auto_active_account` 是待实现的任务框架。

### 任务表结构（task_status）
```javascript
{
  id: 1,
  sn_code: 'GHJU',
  taskType: 'auto_deliver',
  taskName: '自动投递 - 前端开发',
  status: 'running',
  priority: 7,
  taskParams: { keyword: '前端', platform: 'boss' },
  result: {},
  startTime: '2024-01-01 10:00:00',
  endTime: null,
  duration: 0
}
```

### 任务执行流程
```javascript
// 1. 添加任务到队列
await taskQueue.addTask(sn_code, {
  taskType: 'auto_deliver',
  taskName: '自动投递',
  taskParams: { keyword: '前端' }
});

// 2. 任务队列调度执行
// 3. 任务处理器处理任务
// 4. 任务处理器创建并执行指令
```

## ⚙️ 指令（Command）

### 定义
指令是执行层面的概念，代表一个具体的操作，通过 MQTT 发送到客户端执行。

### 特点
- **执行导向**：代表一个具体的操作
- **原子性**：一个指令是一个不可分割的操作
- **有执行顺序**：指令可以按顺序执行
- **有超时机制**：指令级别有超时保护
- **MQTT 通信**：通过 MQTT 发送到客户端

### 指令类型示例
- `getOnlineResume` - 获取在线简历
- `getJobList` - 获取岗位列表
- `applyJob` - 投递简历
- `sendChatMessage` - 发送聊天消息
- `getLoginQrCode` - 获取登录二维码

### 指令表结构（task_commands）
```javascript
{
  id: 1,
  task_id: 100,  // 关联的任务ID
  command_type: 'getOnlineResume',
  command_name: '获取在线简历',
  command_params: '{"sn_code":"GHJU"}',
  status: 'completed',
  sequence: 1,
  priority: 9,
  start_time: '2024-01-01 10:00:00',
  end_time: '2024-01-01 10:00:30',
  duration: 30000
}
```

### 指令执行流程
```javascript
// 1. 任务处理器创建指令
const commands = [{
  command_type: 'getOnlineResume',
  command_name: '获取在线简历',
  command_params: JSON.stringify({ sn_code })
}];

// 2. 指令管理器执行指令
await command.executeCommands(taskId, commands, mqttClient);

// 3. 通过 MQTT 发送到客户端
// 4. 客户端执行并返回结果
```

## 🔗 关系示例

### 示例1：自动投递任务

**任务**：`auto_deliver`（自动投递任务）

**包含的指令**：
1. `getOnlineResume` - 获取在线简历
2. `getJobList` - 获取岗位列表
3. `applyJob` - 投递简历（可能多个）

```javascript
// 任务处理器创建多个指令
async handleAutoDeliverTask(task) {
  // 1. 获取简历指令
  const getResumeCommand = {
    command_type: 'getOnlineResume',
    command_name: '获取在线简历',
    ...
  };
  
  // 2. 获取岗位列表指令
  const getJobListCommand = {
    command_type: 'getJobList',
    command_name: '获取岗位列表',
    ...
  };
  
  // 3. 投递指令（可能多个）
  const applyCommands = jobs.map(job => ({
    command_type: 'applyJob',
    command_name: `投递简历 - ${job.jobTitle}`,
    ...
  }));
  
  // 执行所有指令
  await command.executeCommands(task.id, [
    getResumeCommand,
    getJobListCommand,
    ...applyCommands
  ], mqttClient);
}
```

### 示例2：获取简历（伪任务，实际是指令）

**说明**：虽然代码中有 `get_resume` 任务处理器，但它实际上只是包装了单个指令，本质上就是直接执行指令。

**任务**：`get_resume`（获取简历任务）

**包含的指令**：
1. `getOnlineResume` - 获取在线简历

```javascript
async handleGetResumeTask(task) {
  // 实际上只是创建一个指令并执行
  const commands = [{
    command_type: 'getOnlineResume',
    command_name: '获取在线简历',
    command_params: JSON.stringify({ sn_code: task.sn_code })
  }];
  
  await command.executeCommands(task.id, commands, this.mqttClient);
}
```

**注意**：这种"任务"实际上可以直接作为指令执行，不需要通过任务队列。它们存在的原因可能是为了：
1. 统一的任务追踪和日志记录
2. 未来可能扩展为真正的任务（包含多个步骤）
3. 保持接口的一致性

## 📈 执行流程图

```
┌─────────────────┐
│  任务队列        │
│  (TaskQueue)    │
└────────┬────────┘
         │ 调度任务
         ↓
┌─────────────────┐
│  任务处理器      │
│ (TaskHandlers)  │
└────────┬────────┘
         │ 创建指令
         ↓
┌─────────────────┐
│  指令管理器      │
│ (CommandManager)│
└────────┬────────┘
         │ 执行指令
         ↓
┌─────────────────┐
│  业务管理器      │
│  (jobManager)   │
└────────┬────────┘
         │ MQTT 发送
         ↓
┌─────────────────┐
│  客户端设备      │
│  (Python Client)│
└─────────────────┘
```

## 🎨 设计优势

### 1. **职责分离**
- **任务层**：负责业务逻辑和流程编排
- **指令层**：负责具体操作和 MQTT 通信

### 2. **灵活性**
- 一个任务可以包含不同数量的指令
- 可以根据业务需求动态创建指令

### 3. **可追踪性**
- 任务级别：可以追踪整个业务流程
- 指令级别：可以追踪每个具体操作

### 4. **错误处理**
- 任务级别：处理业务逻辑错误
- 指令级别：处理执行错误和超时

## 📝 代码示例

### 任务处理器创建指令

```javascript
// api/middleware/schedule/taskHandlers.js
async handleAutoDeliverTask(task) {
  const { sn_code, taskParams } = task;
  
  // 1. 创建获取简历指令
  const getResumeCommand = {
    command_type: 'getOnlineResume',
    command_name: '获取在线简历',
    command_params: JSON.stringify({ sn_code, platform: 'boss' })
  };
  
  // 2. 创建获取岗位列表指令
  const getJobListCommand = {
    command_type: 'getJobList',
    command_name: '获取岗位列表',
    command_params: JSON.stringify({ 
      sn_code, 
      keyword: taskParams.keyword,
      platform: 'boss'
    })
  };
  
  // 3. 执行指令序列
  const result = await command.executeCommands(
    task.id, 
    [getResumeCommand, getJobListCommand], 
    this.mqttClient
  );
  
  return result;
}
```

### 指令管理器执行指令

```javascript
// api/middleware/schedule/command.js
async executeCommand(taskId, command, mqttClient) {
  // 1. 创建指令记录
  const commandRecord = await db.getModel('task_commands').create({
    task_id: taskId,
    command_type: command.command_type,
    command_name: command.command_name,
    status: 'pending'
  });
  
  // 2. 调用业务管理器执行
  const result = await jobManager[commandType](
    sn_code, 
    mqttClient, 
    commandParams
  );
  
  // 3. 更新指令状态
  await this.updateCommandStatus(commandId, 'completed', result);
  
  return result;
}
```

## 🔍 总结

- **任务（Task）**：业务层面的工作单元，代表一个完整的业务流程
  - **真正的任务**：包含多个步骤/指令，如 `auto_deliver`
  - **伪任务**：虽然叫任务，但实际只是包装了单个指令，如 `get_resume`、`get_job_list` 等

- **指令（Command）**：执行层面的操作单元，代表一个具体的操作
  - 通过 MQTT 发送到客户端执行
  - 如：`getOnlineResume`、`getJobList`、`applyJob` 等

- **关系**：
  - 真正的任务包含多个指令，指令按顺序执行
  - 伪任务只是指令的包装，本质上就是直接执行指令

- **管理**：任务由任务队列管理，指令由指令管理器管理

- **通信**：任务在服务端内部调度，指令通过 MQTT 发送到客户端

- **当前状态**：
  - 目前系统中只有 `auto_deliver` 是真正的任务（包含多个步骤）
  - 其他如 `get_resume`、`get_job_list`、`send_chat`、`apply_job` 虽然叫任务，但实际只是指令的包装

这种设计实现了业务逻辑和执行逻辑的分离，提高了系统的灵活性和可维护性。伪任务的存在可能是为了统一的任务追踪和未来扩展。

