# 计划任务引擎

<cite>
**本文引用的文件**
- [src/lib/cron/engine.ts](file://src/lib/cron/engine.ts)
- [src/lib/cron/executor.ts](file://src/lib/cron/executor.ts)
- [src/lib/cron/cron-parser.ts](file://src/lib/cron/cron-parser.ts)
- [src/lib/db.ts](file://src/lib/db.ts)
- [src/lib/types.ts](file://src/lib/types.ts)
- [src/app/api/cron-engine/route.ts](file://src/app/api/cron-engine/route.ts)
- [src/app/api/cron-tasks/route.ts](file://src/app/api/cron-tasks/route.ts)
- [src/app/api/task-executions/route.ts](file://src/app/api/task-executions/route.ts)
- [src/hooks/use-cron-tasks.ts](file://src/hooks/use-cron-tasks.ts)
- [src/hooks/use-task-executions.ts](file://src/hooks/use-task-executions.ts)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本文件为“计划任务引擎”的综合技术文档，覆盖任务调度算法、执行器架构与时间触发机制；阐述任务生命周期管理、状态跟踪与执行历史记录；说明任务优先级、并发控制与资源限制策略；包含任务配置管理、依赖关系处理与循环任务支持；提供任务监控、性能统计与故障恢复机制；并说明任务序列化、持久化存储与跨进程通信方案。

## 项目结构
该引擎围绕数据库表 cron_tasks 与 task_executions 展开，通过定时轮询扫描满足条件的任务并异步执行，同时记录每次执行结果与会话信息。前端通过 React Hooks 与后端 API 进行交互，实现任务的增删改查、立即执行与执行历史查询。

```mermaid
graph TB
subgraph "后端"
API1["/api/cron-engine<br/>GET/POST 启停引擎"]
API2["/api/cron-tasks<br/>GET/POST 任务 CRUD"]
API3["/api/task-executions<br/>GET/POST 执行记录"]
Engine["CronEngine 单例<br/>每分钟扫描"]
Parser["Cron 表达式匹配器"]
Executor["任务执行器<br/>Agent/Skill/自定义提示"]
DB["SQLite 数据库<br/>cron_tasks / task_executions"]
end
subgraph "前端"
Hook1["use-cron-tasks.ts"]
Hook2["use-task-executions.ts"]
end
Hook1 --> API2
Hook2 --> API3
API1 --> Engine
API2 --> DB
API3 --> DB
Engine --> Parser
Engine --> Executor
Engine --> DB
Executor --> DB
```

图表来源
- [src/app/api/cron-engine/route.ts:1-30](file://src/app/api/cron-engine/route.ts#L1-L30)
- [src/app/api/cron-tasks/route.ts:1-53](file://src/app/api/cron-tasks/route.ts#L1-L53)
- [src/app/api/task-executions/route.ts:1-76](file://src/app/api/task-executions/route.ts#L1-L76)
- [src/lib/cron/engine.ts:1-121](file://src/lib/cron/engine.ts#L1-L121)
- [src/lib/cron/cron-parser.ts:1-57](file://src/lib/cron/cron-parser.ts#L1-L57)
- [src/lib/cron/executor.ts:1-306](file://src/lib/cron/executor.ts#L1-L306)
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)

章节来源
- [src/app/api/cron-engine/route.ts:1-30](file://src/app/api/cron-engine/route.ts#L1-L30)
- [src/app/api/cron-tasks/route.ts:1-53](file://src/app/api/cron-tasks/route.ts#L1-L53)
- [src/app/api/task-executions/route.ts:1-76](file://src/app/api/task-executions/route.ts#L1-L76)
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)

## 核心组件
- 定时引擎（CronEngine）：单例运行，每分钟检查一次启用的任务，基于 cron 表达式匹配决定是否执行；使用集合避免同一任务并发执行。
- 执行器（Executor）：根据任务类型选择执行路径（心跳、运行代理、运行技能、自定义提示），创建持久化会话并记录消息，必要时通过 IM 桥接层发送通知。
- Cron 解析器（CronParser）：解析并匹配分钟/小时/日/月/周表达式，支持通配符、范围、步进与多值组合。
- 数据层（DB）：初始化并迁移数据库表，维护任务与执行记录，索引优化查询。
- 类型系统（Types）：统一任务、执行记录与配置的数据结构定义。
- 前端 Hooks：封装任务与执行记录的增删改查与分页加载。

章节来源
- [src/lib/cron/engine.ts:16-121](file://src/lib/cron/engine.ts#L16-L121)
- [src/lib/cron/executor.ts:26-306](file://src/lib/cron/executor.ts#L26-L306)
- [src/lib/cron/cron-parser.ts:7-57](file://src/lib/cron/cron-parser.ts#L7-L57)
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)
- [src/lib/types.ts:162-221](file://src/lib/types.ts#L162-L221)
- [src/hooks/use-cron-tasks.ts:47-116](file://src/hooks/use-cron-tasks.ts#L47-L116)
- [src/hooks/use-task-executions.ts:30-98](file://src/hooks/use-task-executions.ts#L30-L98)

## 架构总览
下图展示从 API 到引擎、解析器、执行器与数据库的整体调用链路。

```mermaid
sequenceDiagram
participant FE as "前端"
participant API as "Next.js 路由"
participant Engine as "CronEngine"
participant Parser as "CronParser"
participant Exec as "Executor"
participant DB as "SQLite"
FE->>API : "POST /api/cron-tasks"
API->>DB : "插入 cron_tasks"
API-->>FE : "返回新建任务"
API->>Engine : "GET/POST /api/cron-engine"
Engine->>DB : "查询启用任务"
loop 每分钟
Engine->>Parser : "匹配 cron 表达式"
alt 匹配成功且未在执行
Engine->>Exec : "executeTask(task)"
Exec->>DB : "创建会话/写入消息"
Exec-->>Engine : "返回 {status, result, sessionId}"
Engine->>DB : "写入 task_executions 并更新任务"
else 不匹配或正在执行
Engine-->>Engine : "跳过"
end
end
```

图表来源
- [src/app/api/cron-tasks/route.ts:23-52](file://src/app/api/cron-tasks/route.ts#L23-L52)
- [src/app/api/cron-engine/route.ts:5-29](file://src/app/api/cron-engine/route.ts#L5-L29)
- [src/lib/cron/engine.ts:44-105](file://src/lib/cron/engine.ts#L44-L105)
- [src/lib/cron/cron-parser.ts:7-20](file://src/lib/cron/cron-parser.ts#L7-L20)
- [src/lib/cron/executor.ts:26-47](file://src/lib/cron/executor.ts#L26-L47)
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)

## 详细组件分析

### 组件一：CronEngine（定时引擎）
- 角色与职责
  - 单例模式，按需自动启动（存在启用任务时）。
  - 每分钟扫描一次启用的任务，过滤空表达式与正在执行中的任务。
  - 对匹配的任务异步执行，并在完成后清理执行标记。
  - 自动禁用一次性任务（当 cron 中日与月固定时视为一次性）。
- 关键行为
  - 启停控制：外部 API 或自动启动。
  - 并发控制：使用 Set 记录正在执行的任务 ID，避免重复执行。
  - 执行记录：无论成功或失败均写入 task_executions，并更新任务最近执行信息。
- 复杂度与性能
  - 扫描复杂度 O(N)，N 为启用任务数；每分钟一次，开销可控。
  - 使用内存集合进行并发去重，查找删除均为 O(1)。

```mermaid
classDiagram
class CronEngine {
-timer : Interval
-running : boolean
-executingTasks : Set~string~
+start() void
+stop() void
+isRunning() boolean
-tick() Promise~void~
-runTask(task) Promise~void~
}
class CronTaskRow {
+id : string
+name : string
+schedule : string
+enabled : number
}
CronEngine --> CronTaskRow : "读取并匹配"
```

图表来源
- [src/lib/cron/engine.ts:16-121](file://src/lib/cron/engine.ts#L16-L121)
- [src/lib/types.ts:166-183](file://src/lib/types.ts#L166-L183)

章节来源
- [src/lib/cron/engine.ts:21-105](file://src/lib/cron/engine.ts#L21-L105)

### 组件二：CronParser（Cron 表达式匹配器）
- 支持格式与特性
  - 字段：分钟、小时、日、月、星期（0=周日）。
  - 支持：*, N, N-M, N,M,..., 步进 */N、N-M/N。
- 匹配流程
  - 将表达式拆分为五段，分别与当前时间对应字段比较。
  - 任一段不匹配则整体不匹配。

```mermaid
flowchart TD
Start(["开始"]) --> Split["拆分表达式为5段"]
Split --> Len{"长度==5?"}
Len --> |否| Fail["不匹配"]
Len --> |是| Now["获取当前时间各字段"]
Now --> Loop["逐段匹配"]
Loop --> Field["matchField(field, value)"]
Field --> Ok{"匹配?"}
Ok --> |否| Fail
Ok --> |是| Next["继续下一段"]
Next --> Done{"全部匹配?"}
Done --> |是| True["匹配成功"]
Done --> |否| Loop
```

图表来源
- [src/lib/cron/cron-parser.ts:7-57](file://src/lib/cron/cron-parser.ts#L7-L57)

章节来源
- [src/lib/cron/cron-parser.ts:7-57](file://src/lib/cron/cron-parser.ts#L7-L57)

### 组件三：Executor（任务执行器）
- 任务类型
  - 心跳（Heartbeat）：读取工作区清单文件，执行并根据结果发送 IM 通知。
  - 运行代理（Run-Agent）：加载代理提示文件，以代理身份执行。
  - 运行技能（Run-Skill）：加载技能提示文件，以技能身份执行。
  - 自定义提示（Custom-Prompt）：直接使用用户提供的动作文本。
- 执行流程
  - 解析配置（JSON 字符串），解析工作区 ID（心跳可回退到最近打开的工作区）。
  - 创建持久化会话并在数据库中写入用户消息。
  - 通过 SDK 流式生成内容，拼接文本块作为结果。
  - 写入助手回复消息，触发 IM 事件刷新会话列表。
  - 可选通过 IM 桥接层向指定通道发送通知。
- 并发与资源
  - 由引擎层保证同一任务不会并发执行。
  - 执行器内部无全局共享状态，避免竞争。

```mermaid
sequenceDiagram
participant Engine as "CronEngine"
participant Exec as "Executor"
participant FS as "工作区文件系统"
participant SDK as "Forge SDK"
participant DB as "SQLite"
participant IM as "IM 桥接层"
Engine->>Exec : "executeTask(task)"
Exec->>FS : "读取提示/清单文件"
Exec->>DB : "插入会话与用户消息"
Exec->>SDK : "流式生成内容"
SDK-->>Exec : "文本块"
Exec->>DB : "插入助手回复消息"
Exec->>IM : "通知可选"
Exec-->>Engine : "{status, result, sessionId}"
```

图表来源
- [src/lib/cron/executor.ts:26-306](file://src/lib/cron/executor.ts#L26-L306)
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)

章节来源
- [src/lib/cron/executor.ts:26-306](file://src/lib/cron/executor.ts#L26-L306)

### 组件四：数据库模型与持久化
- 表结构
  - cron_tasks：任务元数据、调度表达式、动作类型、代理/技能名称、工作区 ID、启用状态、配置、最近执行时间与结果等。
  - task_executions：每次执行的结果、状态、关联任务、会话 ID、执行时间。
  - sessions/messages：用于记录执行产生的会话与消息，便于在聊天视图中查看。
- 索引与约束
  - 对 task_executions(task_id, executed_at DESC) 建有索引，提升查询效率。
  - 外键约束确保删除任务时级联删除执行记录。
- 迁移与兼容
  - 首次访问时自动创建表与种子数据（如心跳任务），并进行多版本迁移以适配旧 schema。

```mermaid
erDiagram
CRON_TASKS {
text id PK
text name
text schedule
text action
text action_type
text agent_name
text skill_name
text workspace_id
int enabled
int is_heartbeat
text config
text last_run_at
text last_run_result
text created_at
text updated_at
}
TASK_EXECUTIONS {
text id PK
text task_id FK
text task_name
text result
text status
text session_id
text executed_at
}
SESSIONS {
text id PK
text title
text workspace
text model
text status
text created_at
text updated_at
}
MESSAGES {
text id PK
text session_id FK
text role
text content
text created_at
}
CRON_TASKS ||--o{ TASK_EXECUTIONS : "拥有"
SESSIONS ||--o{ MESSAGES : "包含"
```

图表来源
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)

章节来源
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)

### 组件五：API 与前端集成
- 引擎启停 API：GET 返回运行状态，POST 接收 start/stop 动作。
- 任务 API：GET 支持按工作区筛选；POST 创建任务并自动启动引擎（若尚未运行）。
- 执行记录 API：GET 支持按任务、工作区、类型（心跳/定时）、状态过滤与分页；POST 手动记录执行结果并更新任务。
- 前端 Hooks：
  - use-cron-tasks：任务列表、创建、更新、删除、立即执行。
  - use-task-executions：执行记录列表、分页加载、过滤器。

```mermaid
sequenceDiagram
participant FE as "前端"
participant API as "Next.js 路由"
participant DB as "SQLite"
FE->>API : "GET /api/cron-tasks?workspace_id=..."
API->>DB : "查询任务"
DB-->>API : "返回任务列表"
API-->>FE : "JSON"
FE->>API : "POST /api/cron-tasks"
API->>DB : "插入任务"
API-->>FE : "返回新任务"
```

图表来源
- [src/app/api/cron-tasks/route.ts:6-21](file://src/app/api/cron-tasks/route.ts#L6-L21)
- [src/app/api/cron-tasks/route.ts:23-52](file://src/app/api/cron-tasks/route.ts#L23-L52)
- [src/hooks/use-cron-tasks.ts:47-116](file://src/hooks/use-cron-tasks.ts#L47-L116)

章节来源
- [src/app/api/cron-engine/route.ts:1-30](file://src/app/api/cron-engine/route.ts#L1-L30)
- [src/app/api/cron-tasks/route.ts:1-53](file://src/app/api/cron-tasks/route.ts#L1-L53)
- [src/app/api/task-executions/route.ts:1-76](file://src/app/api/task-executions/route.ts#L1-L76)
- [src/hooks/use-cron-tasks.ts:1-116](file://src/hooks/use-cron-tasks.ts#L1-L116)
- [src/hooks/use-task-executions.ts:1-98](file://src/hooks/use-task-executions.ts#L1-L98)

## 依赖分析
- 组件耦合
  - CronEngine 依赖 CronParser 与 Executor；两者均依赖数据库以写入会话与执行记录。
  - API 层仅作为入口，不承载业务逻辑，降低耦合。
- 外部依赖
  - better-sqlite3：本地嵌入式数据库。
  - IM 桥接层：用于向飞书/电报/Discord 等渠道发送通知。
- 循环依赖
  - 未发现文件级循环导入；模块间通过函数接口解耦。

```mermaid
graph LR
Engine["CronEngine"] --> Parser["CronParser"]
Engine --> Executor["Executor"]
Executor --> DB["DB"]
Engine --> DB
API_Tasks["/api/cron-tasks"] --> DB
API_Exec["/api/task-executions"] --> DB
API_Engine["/api/cron-engine"] --> Engine
```

图表来源
- [src/lib/cron/engine.ts:1-121](file://src/lib/cron/engine.ts#L1-L121)
- [src/lib/cron/executor.ts:1-306](file://src/lib/cron/executor.ts#L1-L306)
- [src/lib/cron/cron-parser.ts:1-57](file://src/lib/cron/cron-parser.ts#L1-L57)
- [src/lib/db.ts:1-499](file://src/lib/db.ts#L1-L499)
- [src/app/api/cron-tasks/route.ts:1-53](file://src/app/api/cron-tasks/route.ts#L1-L53)
- [src/app/api/task-executions/route.ts:1-76](file://src/app/api/task-executions/route.ts#L1-L76)
- [src/app/api/cron-engine/route.ts:1-30](file://src/app/api/cron-engine/route.ts#L1-L30)

章节来源
- [src/lib/cron/engine.ts:1-121](file://src/lib/cron/engine.ts#L1-L121)
- [src/lib/cron/executor.ts:1-306](file://src/lib/cron/executor.ts#L1-L306)
- [src/lib/cron/cron-parser.ts:1-57](file://src/lib/cron/cron-parser.ts#L1-L57)
- [src/lib/db.ts:1-499](file://src/lib/db.ts#L1-L499)

## 性能考虑
- 扫描频率与负载
  - 每分钟扫描一次启用任务，对小中规模任务集开销极低。
- 并发与去重
  - 使用 Set 去重，避免重复执行同一任务，减少资源浪费。
- 查询优化
  - task_executions 表对 (task_id, executed_at DESC) 建有索引，支持高效分页与过滤。
- I/O 与序列化
  - 会话与消息写入数据库，避免内存膨胀；配置以 JSON 字符串存储，解析成本低。
- 扩展建议
  - 若任务数量增长，可考虑：
    - 将任务按工作区分区或增加索引；
    - 引入轻量队列或信号机制替代每分钟轮询；
    - 对长耗时任务引入超时与中断能力。

## 故障排查指南
- 引擎无法启动
  - 检查是否存在启用任务；引擎会在存在启用任务时自动启动。
  - 通过 GET /api/cron-engine 确认运行状态。
- 任务未执行
  - 确认任务已启用且 cron 表达式有效。
  - 查看 task_executions 是否有对应记录；若无，检查引擎日志与数据库连接。
- 执行失败
  - 查看 task_executions 的 status 与 result 字段；错误会被记录为 error 状态。
  - 检查工作区文件是否存在（心跳清单、代理/技能提示文件）。
- IM 通知未送达
  - 确认通道已连接且存在绑定；检查通道绑定表与桥接层状态。
- 会话未出现在聊天列表
  - 确认执行器已创建会话并写入 messages；检查 sessions 与 messages 表。

章节来源
- [src/lib/cron/engine.ts:108-121](file://src/lib/cron/engine.ts#L108-L121)
- [src/app/api/cron-engine/route.ts:5-8](file://src/app/api/cron-engine/route.ts#L5-L8)
- [src/app/api/task-executions/route.ts:51-76](file://src/app/api/task-executions/route.ts#L51-L76)
- [src/lib/cron/executor.ts:261-297](file://src/lib/cron/executor.ts#L261-L297)
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)

## 结论
该计划任务引擎以简洁可靠为核心设计目标：基于每分钟轮询与表达式匹配的调度方式，结合执行器的会话持久化与 IM 通知能力，形成完整的任务生命周期闭环。通过 SQLite 的本地化存储与索引优化，满足中小规模场景下的可用性与性能需求。未来可在任务分片、事件驱动与资源隔离方面进一步演进。

## 附录

### 任务生命周期与状态流转
```mermaid
stateDiagram-v2
[*] --> 已创建
已创建 --> 已启用 : "设置 enabled=true"
已启用 --> 已禁用 : "手动/一次性任务执行后"
已启用 --> 已启用 : "执行中"
已启用 --> 错误 : "执行异常"
已启用 --> 已启用 : "下次周期匹配"
错误 --> 已启用 : "修复后重新启用"
```

[此图为概念性状态图，无需图表来源]

### 任务配置与字段说明
- 任务表（cron_tasks）
  - id/name/schedule/action/action_type/agent_name/skill_name/workspace_id/enabled/is_heartbeat/config/last_run_at/last_run_result/created_at/updated_at
- 执行记录表（task_executions）
  - id/task_id/task_name/result/status/session_id/executed_at
- 类型定义（CronTaskRow/CronTask/TaskExecution）
  - 提供数据库行与应用层对象之间的映射与校验。

章节来源
- [src/lib/db.ts:117-147](file://src/lib/db.ts#L117-L147)
- [src/lib/types.ts:166-221](file://src/lib/types.ts#L166-L221)