Files
TrueGrowth/specs/001-batch-task-queue/plan.md

666 lines
22 KiB
Markdown
Raw 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.
# 实施计划:内容生成批量任务队列
**分支**: `001-batch-task-queue` | **日期**: 2025-11-22 | **规格**: [spec.md](./spec.md)
**输入**: 功能规格来自 `/specs/001-batch-task-queue/spec.md`
## 摘要
实现异步内容生成任务队列系统,允许用户提交图片和视频生成请求而无需等待完成。系统将在浏览器本地存储任务数据,通过页面底部固定工具栏提供任务监控和管理界面。核心技术方案采用 React + TypeScript + localforage集成到现有的 Opentu 白板应用架构中。
## 技术上下文
**语言/版本**: TypeScript 5.4+ / React 18.3+
**主要依赖**:
- localforage 1.10+ (浏览器本地存储)
- TDesign React 1.14+ (UI 组件库)
- RxJS 7.8+ (异步事件流管理)
- Plait 框架 (现有白板核心)
**存储**: IndexedDB (通过 localforage 抽象层)
**测试**: Jest + React Testing Library (单元测试), Playwright (E2E 测试)
**目标平台**: Web 浏览器 (Chrome 90+, Firefox 88+, Safari 14+)
**项目类型**: Web 应用 (Nx monorepo 中的 packages/drawnix 扩展)
**性能目标**:
- 任务队列 UI 响应 < 200ms
- 本地存储读写 < 100ms
- 支持 100+ 并发任务无性能下降
- 60 FPS 动画流畅度
**约束**:
- 单文件不超过 500 行代码
- 浏览器本地存储限制 (IndexedDB ~50MB)
- 无服务器端持久化
- 兼容现有 Plait 插件架构
**规模/范围**:
- 新增 8-12 个 React 组件
- 新增 4-6 个自定义 Hooks
- 新增 3-5 个工具模块
- 预计 2000-3000 行新代码
## 项目结构
### 文档 (本功能)
```text
specs/001-batch-task-queue/
├── plan.md # 本文件 (/speckit.plan 命令输出)
├── spec.md # 功能规格说明
├── checklists/ # 质量检查清单
│ └── requirements.md # 需求完整性检查
└── tasks.md # 阶段 2 输出 (/speckit.tasks 命令 - 尚未创建)
```
### 源代码 (仓库根目录)
```text
packages/drawnix/src/
├── components/
│ ├── task-queue/ # 新增:任务队列组件
│ │ ├── TaskToolbar.tsx # 底部固定工具栏
│ │ ├── TaskQueuePanel.tsx # 可展开的任务队列面板
│ │ ├── TaskItem.tsx # 单个任务项组件
│ │ ├── TaskSummary.tsx # 任务摘要显示
│ │ └── task-queue.scss # 样式文件
│ └── toolbar/
│ └── creation-toolbar.tsx # 修改:集成任务创建
├── hooks/
│ ├── useTaskQueue.ts # 新增:任务队列管理 Hook
│ ├── useTaskStorage.ts # 新增:本地存储操作 Hook
│ ├── useTaskExecutor.ts # 新增:任务执行器 Hook
│ └── useRetryStrategy.ts # 新增:重试策略 Hook
├── services/
│ ├── task-queue-service.ts # 新增:任务队列核心服务
│ ├── generation-api-service.ts # 新增AI 生成 API 调用服务
│ └── storage-service.ts # 新增IndexedDB 存储服务
├── utils/
│ ├── task-utils.ts # 新增:任务工具函数
│ ├── retry-utils.ts # 新增:重试策略工具
│ └── validation-utils.ts # 新增:参数验证工具
├── types/
│ ├── task.types.ts # 新增:任务相关类型定义
│ └── generation.types.ts # 新增:生成相关类型定义
├── constants/
│ └── TASK_CONSTANTS.ts # 新增:任务相关常量
└── drawnix.tsx # 修改:集成任务队列上下文
tests/
├── unit/
│ ├── task-queue-service.spec.ts
│ ├── useTaskQueue.spec.ts
│ ├── retry-utils.spec.ts
│ └── TaskToolbar.spec.tsx
└── integration/
└── task-queue-flow.spec.ts
```
**结构决策**: 采用单一 Web 应用结构,在现有 `packages/drawnix` 包中扩展功能。选择此结构是因为:
1. 任务队列是白板应用的核心功能扩展,不是独立应用
2. 需要与现有组件creation-toolbar深度集成
3. 共享现有的 UI 组件库和样式系统
4. 保持 Nx monorepo 的一致性
## 系统架构
### 架构层次
```text
┌─────────────────────────────────────────────────────────────┐
│ UI Layer (React Components) │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ TaskToolbar │ │ Creation │ │
│ │ (Bottom Bar) │ │ Toolbar │ │
│ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │
│ ┌────────▼──────────────────────▼─────────┐ │
│ │ TaskQueuePanel (Expandable) │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │TaskItem │ │TaskItem │ │TaskItem │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────▼─────────────────────────────────────┐
│ Business Logic Layer (Hooks & Services) │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ useTaskQueue │ │ useTaskExecutor │ │
│ │ (State Mgmt) │ │ (Execution) │ │
│ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │
│ ┌────────▼──────────────────────▼─────────┐ │
│ │ TaskQueueService (Core Logic) │ │
│ │ - Task CRUD │ │
│ │ - Status Management │ │
│ │ - Event Emission (RxJS) │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────▼─────────────────────────────────────┐
│ Integration Layer (External Services) │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ StorageService │ │ GenerationAPI │ │
│ │ (IndexedDB) │ │ Service │ │
│ │ - localforage │ │ (AI 生成) │ │
│ └──────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### 核心组件职责
**TaskToolbar (底部工具栏)**
- 显示任务摘要(生成中/完成/失败计数)
- 响应点击展开/收起队列面板
- 显示新任务完成通知
- 固定在页面底部,不遮挡主工作区
**TaskQueuePanel (任务队列面板)**
- 展开/收起动画60 FPS
- 显示所有任务的列表视图
- 支持按状态筛选(全部/待处理/处理中/已完成/失败)
- 虚拟滚动支持(处理 100+ 任务)
**TaskItem (任务项)**
- 显示任务详细信息(类型、参数、状态、进度)
- 显示重试计数和下次重试时间
- 提供操作按钮(取消/重试/删除/下载)
- 实时状态更新
**TaskQueueService (核心服务)**
- 单例模式,全局任务队列管理
- RxJS Subject 发布任务状态变化事件
- 支持 CRUD 操作(创建、读取、更新、删除任务)
- 超时检测和自动标记失败
- 防重复提交检测5秒窗口
**useTaskQueue (状态管理 Hook)**
- 订阅 TaskQueueService 的事件流
- 提供 React 组件友好的状态和方法
- 自动同步到本地存储
- 处理组件挂载/卸载时的订阅清理
**useTaskExecutor (执行器 Hook)**
- 管理单个任务的执行生命周期
- 实施指数退避重试策略1min, 5min, 15min
- 处理超时检测(图片 10min, 视频 30min
- 调用 GenerationAPIService 执行实际生成
**StorageService (存储服务)**
- 封装 localforage API
- 提供任务队列的持久化和恢复
- 处理 IndexedDB 容量限制
- 支持数据迁移和版本管理
**GenerationAPIService (生成 API 服务)**
- 调用后台 AI 生成服务(图片/视频)
- 处理请求超时和网络错误
- 返回标准化的响应格式
- 支持请求取消AbortController
### 数据流
**任务创建流程**:
```text
1. 用户在 CreationToolbar 填写表单,点击"生成"
2. 表单验证 → 失败则提示错误
3. 创建任务对象 (TaskQueueService.createTask)
4. 防重复检查 → 如重复则拒绝
5. 添加到队列 → 发出 'taskCreated' 事件
6. 保存到 IndexedDB (StorageService)
7. 重置表单为初始状态
8. 更新 TaskToolbar 摘要显示
9. useTaskExecutor 监听到新任务 → 开始执行
```
**任务执行流程**:
```text
1. useTaskExecutor 检测到 'pending' 状态任务
2. 更新状态为 'processing' → 发出事件 → 保存
3. 调用 GenerationAPIService.generate(params)
4. 设置超时定时器 (图片 10min / 视频 30min)
5a. 成功响应 → 更新状态为 'completed' → 保存结果
5b. 失败响应 → 检查重试次数
- 未达上限 → 进入 'retrying' 状态 → 设置重试定时器
- 已达上限 → 更新状态为 'failed' → 保存错误信息
5c. 超时 → 更新状态为 'failed' (超时错误)
6. 清除定时器,发出状态变化事件
7. 更新 UI 显示
```
**状态同步流程**:
```text
1. TaskQueueService 发出事件 (RxJS Subject)
2. useTaskQueue 订阅并更新 React 状态
3. React 组件重新渲染
4. StorageService 异步写入 IndexedDB
5. 页面刷新时,从 IndexedDB 恢复状态
```
## 数据模型
### 核心类型定义
```typescript
// task.types.ts
export enum TaskStatus {
PENDING = 'pending',
PROCESSING = 'processing',
RETRYING = 'retrying',
COMPLETED = 'completed',
FAILED = 'failed',
CANCELLED = 'cancelled'
}
export enum TaskType {
IMAGE = 'image',
VIDEO = 'video'
}
export interface GenerationParams {
prompt: string;
width?: number;
height?: number;
duration?: number; // 仅视频
style?: string;
seed?: number;
[key: string]: any; // 扩展参数
}
export interface Task {
id: string; // UUID
type: TaskType;
status: TaskStatus;
params: GenerationParams;
createdAt: number; // Unix timestamp (ms)
updatedAt: number;
startedAt?: number;
completedAt?: number;
result?: TaskResult;
error?: TaskError;
retryCount: number;
nextRetryAt?: number;
userId?: string; // 预留多用户支持
}
export interface TaskResult {
url: string; // 生成内容的 URL
format: string; // 文件格式 (png, jpg, mp4)
size: number; // 文件大小 (bytes)
width?: number;
height?: number;
duration?: number; // 仅视频
}
export interface TaskError {
code: string; // 错误代码 (TIMEOUT, NETWORK, API_ERROR, etc.)
message: string;
details?: any;
}
export interface TaskQueueState {
tasks: Map<string, Task>; // taskId -> Task
taskOrder: string[]; // 按创建时间排序的 taskId 数组
}
```
### 本地存储模式
**IndexedDB 数据库结构**:
```text
数据库名: aitu-task-queue
版本: 1
Object Store: tasks
- keyPath: id
- 索引:
- status (非唯一)
- createdAt (非唯一)
- type (非唯一)
```
**存储策略**:
- 每次任务状态变化时异步写入
- 应用启动时一次性读取所有任务
- 定期清理已完成/失败任务(保留最近 100 个)
- 超过 50MB 时警告用户
## 关键决策
### 1. 存储技术选择IndexedDB vs LocalStorage
**决策**: 使用 IndexedDB (通过 localforage 封装)
**理由**:
- LocalStorage 容量限制 ~5MB无法支持 100+ 任务队列
- IndexedDB 支持异步操作,不阻塞 UI
- localforage 提供简洁的 Promise API降低复杂度
- IndexedDB 支持索引,便于按状态筛选任务
### 2. 状态管理Context vs 全局 Service
**决策**: 混合模式 - 全局 Service + React Context
**理由**:
- TaskQueueService 作为单例,提供框架无关的核心逻辑
- useTaskQueue Hook 桥接 Service 和 React 生态
- 便于单元测试Service 可独立测试)
- 未来可支持其他 UI 框架Angular/Vue
### 3. 重试策略:立即重试 vs 指数退避
**决策**: 指数退避1min, 5min, 15min
**理由**:
- 防止服务故障时的雷击效应
- 给后端服务恢复时间
- 规格明确要求指数退避
- 最多 3 次重试,总等待时间 ~21 分钟
### 4. UI 位置:侧边栏 vs 底部工具栏
**决策**: 底部固定工具栏 + 可展开面板
**理由**:
- 规格明确要求底部工具栏
- 不遮挡主白板工作区
- 摘要常驻可见,快速了解任务状态
- 展开面板支持详细管理
### 5. 任务执行:前端轮询 vs 后端推送
**决策**: 前端主动执行 + 轮询状态
**理由**:
- 无服务器端持久化(规格约束)
- 简化架构,减少后端依赖
- 浏览器关闭时任务暂停,重新打开时恢复
- 适合单用户场景
## 实施阶段
### 阶段 0: 基础设施P1 依赖)
**任务**:
1. 创建类型定义文件 (task.types.ts, generation.types.ts)
2. 实现 StorageService (IndexedDB 封装)
3. 实现 TaskQueueService 核心逻辑(无 UI
4. 实现 retry-utils指数退避策略
5. 编写单元测试StorageService, TaskQueueService, retry-utils
**验收标准**:
- StorageService 可读写任务数据
- TaskQueueService 可创建/更新/删除任务
- 重试策略正确计算延迟时间
- 测试覆盖率 > 80%
### 阶段 1: 任务创建与持久化P1
**任务**:
1. 实现 useTaskQueue Hook
2. 实现 useTaskStorage Hook本地存储同步
3. 修改 CreationToolbar集成任务创建
4. 实现 TaskToolbar 组件(摘要显示)
5. 实现表单重置逻辑
6. 编写组件测试
**验收标准**:
- 用户点击"生成"后,任务添加到队列
- 表单在 500ms 内重置
- TaskToolbar 显示正确的任务计数
- 刷新页面后,任务队列恢复
### 阶段 2: 任务执行与监控P2
**任务**:
1. 实现 GenerationAPIService模拟 AI 生成 API
2. 实现 useTaskExecutor Hook
3. 实现 TaskQueuePanel 组件(展开/收起)
4. 实现 TaskItem 组件(任务详情)
5. 实现超时检测逻辑
6. 实现重试逻辑(指数退避)
7. 编写集成测试
**验收标准**:
- 任务自动开始执行
- 状态实时更新5秒内
- 超时任务正确标记为失败
- 失败任务自动重试(最多 3 次)
- 展开/收起动画流畅60 FPS
### 阶段 3: 内容访问与管理P2-P3
**任务**:
1. 实现任务结果预览功能
2. 实现下载/插入操作
3. 实现任务取消功能
4. 实现任务重试功能
5. 实现清除已完成任务功能
6. 添加任务完成通知
7. 编写 E2E 测试
**验收标准**:
- 用户可预览生成的图片/视频
- 用户可下载或插入内容到白板
- 用户可取消待处理/处理中任务
- 用户可手动重试失败任务
- 完成通知正确显示
### 阶段 4: 优化与边界情况P3
**任务**:
1. 实现虚拟滚动(支持 100+ 任务)
2. 实现防重复提交检测5秒窗口
3. 添加任务按状态筛选
4. 优化 IndexedDB 性能
5. 添加错误边界处理
6. 性能测试和优化
7. 完善文档
**验收标准**:
- 100+ 任务时 UI 响应 < 2秒
- 重复提交被正确拦截
- 筛选功能正常工作
- 所有边界情况正常处理
- 性能目标全部达成
## 技术约束与风险
### 约束
1. **单文件 500 行限制**
- 风险:大型组件可能超限
- 缓解:严格组件拆分,提取子组件和 Hooks
2. **浏览器存储限制**
- 风险IndexedDB ~50MB可能不足
- 缓解:定期清理旧任务,保留最近 100 个
3. **无服务器端持久化**
- 风险:跨设备/浏览器无法同步
- 缓解:在 UI 中明确提示用户
4. **浏览器关闭时任务暂停**
- 风险:长视频生成可能中断
- 缓解:提示用户保持页面打开
### 风险
1. **后台 AI 服务不稳定**
- 影响:任务大量失败
- 缓解:指数退避重试,清晰的错误提示
2. **浏览器兼容性**
- 影响IndexedDB 在旧浏览器可能不可用
- 缓解:降级到 LocalStorage限制任务数量
3. **性能问题100+ 任务)**
- 影响UI 卡顿
- 缓解:虚拟滚动,分页加载
4. **内存泄漏**
- 影响:长时间运行后浏览器崩溃
- 缓解:正确清理 RxJS 订阅,定期清理已完成任务
## 测试策略
### 单元测试
**目标覆盖率**: 80%+
**重点测试模块**:
- StorageService: CRUD 操作,错误处理
- TaskQueueService: 状态管理,事件发布
- retry-utils: 延迟计算,边界情况
- validation-utils: 参数验证
### 组件测试
**重点组件**:
- TaskToolbar: 摘要显示,点击展开
- TaskQueuePanel: 展开/收起,任务列表渲染
- TaskItem: 状态显示,操作按钮
**测试场景**:
- 不同任务状态下的 UI 渲染
- 用户交互(点击、输入)
- 状态变化时的重新渲染
- 边界情况(空队列、大量任务)
### 集成测试
**关键流程**:
1. 完整任务生命周期(创建 → 执行 → 完成)
2. 任务失败与重试
3. 任务超时处理
4. 本地存储持久化与恢复
### E2E 测试
**关键用户场景**:
1. 用户提交图片生成任务 → 查看进度 → 下载结果
2. 用户提交多个任务 → 管理队列 → 取消任务
3. 用户刷新页面 → 任务队列恢复
4. 任务失败 → 自动重试 → 最终失败
## 性能目标
| 指标 | 目标 | 测量方法 |
|------|------|---------|
| 任务创建响应时间 | < 200ms | Performance API |
| 表单重置时间 | < 500ms | Performance API |
| 状态更新延迟 | < 5s | 时间戳对比 |
| 工具栏展开/收起 | < 200ms, 60 FPS | Chrome DevTools Performance |
| 本地存储读取 | < 1s (100 任务) | Performance API |
| 本地存储写入 | < 100ms | Performance API |
| 100+ 任务 UI 响应 | < 2s | Performance API |
## 可观测性
### 日志记录
**日志级别**:
- ERROR: 任务失败、存储错误、API 错误
- WARN: 重试触发、超时警告、容量警告
- INFO: 任务创建、状态变化、用户操作
- DEBUG: 内部状态变化、存储操作
**日志格式**:
```typescript
{
timestamp: number,
level: 'ERROR' | 'WARN' | 'INFO' | 'DEBUG',
category: 'TASK' | 'STORAGE' | 'API' | 'UI',
message: string,
taskId?: string,
error?: Error,
metadata?: object
}
```
### 监控指标
**业务指标**:
- 任务创建速率(每分钟)
- 任务完成率
- 任务失败率
- 平均任务执行时间
- 重试次数分布
**技术指标**:
- 本地存储容量使用
- IndexedDB 读写耗时
- 组件渲染耗时
- 内存使用趋势
## 部署与回滚
### 部署策略
**渐进式发布**:
1. 内部测试环境develop 分支)
2. Beta 用户测试staging 环境)
3. 生产环境灰度发布10% → 50% → 100%
**功能开关**:
- 在 Opentu Context 中添加 `enableTaskQueue` 标志
- 允许动态启用/禁用功能
- 便于快速回滚
### 回滚计划
**触发条件**:
- 任务失败率 > 30%
- 页面崩溃率 > 5%
- 用户投诉 > 阈值
**回滚步骤**:
1. 设置 `enableTaskQueue = false`
2. 推送配置更新
3. 监控系统恢复
4. 分析失败原因
5. 修复后重新发布
## 文档交付
1. **用户文档**:
- 功能使用指南
- 常见问题 FAQ
- 故障排查指南
2. **开发者文档**:
- API 参考文档
- 架构设计文档
- 代码注释JSDoc
3. **运维文档**:
- 监控指标说明
- 告警阈值配置
- 应急响应流程
## 后续优化方向
### 短期 (1-3 个月)
- 添加任务优先级支持
- 优化大批量任务性能
- 增强错误提示的友好性
- 添加任务执行历史统计
### 中期 (3-6 个月)
- 支持任务分组和标签
- 添加任务执行进度条
- 实现任务导出/导入功能
- 添加任务模板功能
### 长期 (6-12 个月)
- 服务器端持久化(可选)
- 多设备同步
- 协作队列(多用户共享)
- 任务调度优化(优先级队列)