Initial TrueGrowth source import
This commit is contained in:
53
specs/001-batch-task-queue/checklists/requirements.md
Normal file
53
specs/001-batch-task-queue/checklists/requirements.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 规格说明质量检查清单:内容生成批量任务队列
|
||||
|
||||
**目的**: 在进入规划阶段之前验证规格说明的完整性和质量
|
||||
**创建日期**: 2025-11-22
|
||||
**功能**: [spec.md](../spec.md)
|
||||
|
||||
## 内容质量
|
||||
|
||||
- [x] 无实现细节(语言、框架、API)
|
||||
- [x] 专注于用户价值和业务需求
|
||||
- [x] 为非技术干系人编写
|
||||
- [x] 所有必填部分已完成
|
||||
|
||||
**说明**: 规格说明中没有实现细节。所有需求描述的是用户需要什么,而不是如何实现。语言对非技术干系人易于理解。
|
||||
|
||||
## 需求完整性
|
||||
|
||||
- [x] 不存在 [需要澄清] 标记
|
||||
- [x] 需求可测试且明确
|
||||
- [x] 成功标准可衡量
|
||||
- [x] 成功标准与技术无关(无实现细节)
|
||||
- [x] 所有验收场景已定义
|
||||
- [x] 边界情况已识别
|
||||
- [x] 范围边界清晰
|
||||
- [x] 依赖关系和假设已识别
|
||||
|
||||
**说明**: 所有需求都有明确的验收标准。成功标准包含具体指标(时间、百分比)且以用户为中心。边界情况全面覆盖了边界条件、错误场景和多用户情况。不存在澄清标记 - 所有方面都基于功能描述并使用合理默认值得出。
|
||||
|
||||
## 功能就绪性
|
||||
|
||||
- [x] 所有功能需求都有明确的验收标准
|
||||
- [x] 用户场景涵盖主要流程
|
||||
- [x] 功能满足成功标准中定义的可衡量成果
|
||||
- [x] 规格说明中没有实现细节泄漏
|
||||
|
||||
**说明**: 所有用户故事都有使用"假设-当-那么"格式的详细验收场景。用户故事已优先排序(P1-P3)且可独立测试。成功标准可衡量且与技术无关。
|
||||
|
||||
## 验证摘要
|
||||
|
||||
**状态**: ✅ 通过 - 所有质量检查均已满足
|
||||
|
||||
**主要优势**:
|
||||
1. 用户故事从 P1(核心任务提交)到 P3(高级管理)的清晰优先级排序
|
||||
2. 每个用户故事都可独立测试,价值交付明确
|
||||
3. 全面的边界情况覆盖,包括浏览器会话、失败、容量限制
|
||||
4. 成功标准包含定量(基于时间)和用户体验指标
|
||||
5. 功能需求具体且可测试
|
||||
6. 不存在实现细节 - 纯粹以业务和用户为中心
|
||||
|
||||
**准备进入**: `/speckit.plan` - 规格说明已完成,可以进行实施规划
|
||||
|
||||
**建议**:
|
||||
- 无 - 规格说明满足所有质量标准
|
||||
665
specs/001-batch-task-queue/plan.md
Normal file
665
specs/001-batch-task-queue/plan.md
Normal file
@@ -0,0 +1,665 @@
|
||||
# 实施计划:内容生成批量任务队列
|
||||
|
||||
**分支**: `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 个月)
|
||||
- 服务器端持久化(可选)
|
||||
- 多设备同步
|
||||
- 协作队列(多用户共享)
|
||||
- 任务调度优化(优先级队列)
|
||||
178
specs/001-batch-task-queue/spec.md
Normal file
178
specs/001-batch-task-queue/spec.md
Normal file
@@ -0,0 +1,178 @@
|
||||
# 功能规格说明:内容生成批量任务队列
|
||||
|
||||
**功能分支**: `001-batch-task-queue`
|
||||
**创建日期**: 2025-11-22
|
||||
**状态**: 草稿
|
||||
**输入**: 用户描述: "增加批量任务支持.图片或视频,点击生成之后,创建一个前端任务,后台进行生成.表单恢复初始状态,可以继续创建新的生成任务"
|
||||
|
||||
## 澄清记录
|
||||
|
||||
### 会话 2025-11-22
|
||||
|
||||
- Q: 当后台 AI 生成服务(图片/视频生成 API)完全不可用或响应超时时,系统应如何处理已排队的任务? → A: 使用指数退避策略自动重试(例如:1分钟、5分钟、15分钟),超过最大重试次数(如3次)后标记为失败
|
||||
- Q: 每个用户的任务队列应该有容量限制吗? → A: 无限制,允许用户提交任意数量的任务
|
||||
- Q: 对于图片和视频生成任务,系统应该设置多长的超时时间,超过这个时间后将任务标记为失败? → A: 长超时(图片 10 分钟,视频 30 分钟)
|
||||
- Q: 任务数据(队列、状态、参数、结果)应该存储在哪里以确保跨会话持久化? → A: 仅浏览器本地存储(LocalStorage 或 IndexedDB)
|
||||
- Q: 任务队列应该如何呈现给用户,以便用户可以方便地监控和管理任务? → A: 页面底部固定工具栏,显示任务摘要,点击展开完整队列
|
||||
|
||||
## 用户场景与测试 *(必填)*
|
||||
|
||||
### 用户故事 1 - 提交内容生成任务 (优先级: P1)
|
||||
|
||||
用户需要提交图片或视频生成请求,而无需等待生成完成,从而可以继续处理其他任务或连续提交多个请求。
|
||||
|
||||
**优先级理由**: 这是实现异步内容生成的核心功能。没有这个功能,用户在内容生成期间会被阻塞,完全无法进行批量操作。
|
||||
|
||||
**独立测试**: 可以通过提交单个生成请求、验证任务出现在队列中、确认表单重置来完整测试。通过解放用户无需等待即可立即交付价值。
|
||||
|
||||
**验收场景**:
|
||||
|
||||
1. **假设** 用户已填写图片生成表单,**当** 用户点击"生成",**那么** 创建一个任务并出现在任务队列中,表单重置为初始状态
|
||||
2. **假设** 用户已填写视频生成表单,**当** 用户点击"生成",**那么** 创建一个任务并出现在任务队列中,表单重置为初始状态
|
||||
3. **假设** 生成任务已提交,**当** 用户查看任务队列,**那么** 任务显示为"待处理"或"处理中"状态
|
||||
4. **假设** 表单已提交,**当** 表单重置,**那么** 所有字段恢复为默认值,用户可以立即创建新任务
|
||||
5. **假设** 用户提交任务,**当** 队列中已有大量任务,**那么** 新任务仍然可以成功添加到队列,无容量限制阻止
|
||||
6. **假设** 任务已创建,**当** 任务添加到队列,**那么** 页面底部工具栏显示任务摘要(例如:"3 个任务处理中")
|
||||
|
||||
---
|
||||
|
||||
### 用户故事 2 - 监控任务进度 (优先级: P2)
|
||||
|
||||
用户需要跟踪已提交生成任务的状态,以便知道内容何时准备就绪或任务是否失败。
|
||||
|
||||
**优先级理由**: 对用户感知和任务管理至关重要,但用户仍然可以在没有全面监控的情况下提交任务。
|
||||
|
||||
**独立测试**: 可以通过提交任务并验证状态更新在任务列表中正确显示来测试。通过提供生成进度的可见性来交付价值。
|
||||
|
||||
**验收场景**:
|
||||
|
||||
1. **假设** 用户已提交多个任务,**当** 用户查看任务队列,**那么** 所有任务都显示其当前状态(待处理、处理中、已完成、失败)
|
||||
2. **假设** 任务正在处理中,**当** 生成成功完成,**那么** 任务状态更新为"已完成",生成的内容变为可访问
|
||||
3. **假设** 任务正在处理中,**当** 生成失败,**那么** 任务状态更新为"失败",并显示解释问题的错误消息
|
||||
4. **假设** 任务处于各种状态,**当** 用户刷新页面,**那么** 所有任务状态从浏览器本地存储恢复并保持准确
|
||||
5. **假设** 后台生成服务不可用,**当** 任务自动重试,**那么** 用户在任务详情中看到重试计数和下次重试时间
|
||||
6. **假设** 图片生成任务处理超过 10 分钟,**当** 达到超时限制,**那么** 任务被标记为失败并显示超时错误消息
|
||||
7. **假设** 视频生成任务处理超过 30 分钟,**当** 达到超时限制,**那么** 任务被标记为失败并显示超时错误消息
|
||||
8. **假设** 用户查看底部工具栏,**当** 点击任务摘要区域,**那么** 完整的任务队列展开显示,包含所有任务的详细信息
|
||||
9. **假设** 任务队列已展开,**当** 用户再次点击或点击关闭按钮,**那么** 队列收起,仅显示摘要信息
|
||||
|
||||
---
|
||||
|
||||
### 用户故事 3 - 访问生成的内容 (优先级: P2)
|
||||
|
||||
用户需要检索和使用已完成生成任务的内容。
|
||||
|
||||
**优先级理由**: 对任务价值交付至关重要,但优先级略低于监控,因为用户需要先知道任务完成才能访问结果。
|
||||
|
||||
**独立测试**: 可以通过完成生成任务并验证用户可以下载或插入生成的内容来测试。通过提供最终输出来交付价值。
|
||||
|
||||
**验收场景**:
|
||||
|
||||
1. **假设** 任务已成功完成,**当** 用户查看已完成的任务,**那么** 用户可以预览生成的图片或视频
|
||||
2. **假设** 已完成的任务包含生成的内容,**当** 用户点击下载/插入操作,**那么** 内容可在白板中使用或保存到设备
|
||||
3. **假设** 存在多个已完成的任务,**当** 用户浏览已完成的任务,**那么** 用户可以轻松识别和访问每个生成的内容
|
||||
4. **假设** 任务完成,**当** 底部工具栏显示通知(例如:"1 个新任务完成"),**那么** 用户点击可快速访问已完成的内容
|
||||
|
||||
---
|
||||
|
||||
### 用户故事 4 - 批量提交多个任务 (优先级: P3)
|
||||
|
||||
高级用户需要快速连续提交多个生成请求,以批量创建内容。
|
||||
|
||||
**优先级理由**: 增强高级工作流的生产力,但建立在 P1 基础之上。一旦实现 P1,用户已经可以顺序提交多个任务。
|
||||
|
||||
**独立测试**: 可以通过快速连续提交 5-10 个任务并验证所有任务都正确排队来测试。通过最大化批量操作的吞吐量来交付价值。
|
||||
|
||||
**验收场景**:
|
||||
|
||||
1. **假设** 用户已提交一个任务,**当** 表单重置,**那么** 用户可以立即修改参数并提交另一个任务,无需延迟
|
||||
2. **假设** 用户想生成 10 个变体,**当** 用户连续提交任务,**那么** 所有任务按顺序排队和处理
|
||||
3. **假设** 快速提交多个任务,**当** 查看任务队列,**那么** 所有任务都显示唯一标识符和正确参数
|
||||
|
||||
---
|
||||
|
||||
### 用户故事 5 - 管理任务队列 (优先级: P3)
|
||||
|
||||
用户需要管理任务队列,包括取消待处理任务或清除已完成/失败的任务。
|
||||
|
||||
**优先级理由**: 改善用户控制和队列管理,但如果任务能够合理快速完成,用户可以在没有取消功能的情况下运行。
|
||||
|
||||
**独立测试**: 可以通过提交任务然后从队列中取消/删除它们来测试。通过让用户控制资源使用来交付价值。
|
||||
|
||||
**验收场景**:
|
||||
|
||||
1. **假设** 任务待处理或处理中,**当** 用户点击任务的"取消",**那么** 任务从队列中删除或标记为已取消
|
||||
2. **假设** 存在多个已完成的任务,**当** 用户点击"清除已完成",**那么** 所有已完成的任务从可见队列中删除
|
||||
3. **假设** 队列中存在失败的任务,**当** 用户点击失败任务的"重试",**那么** 使用相同参数将任务重新提交到队列
|
||||
|
||||
---
|
||||
|
||||
### 边界情况
|
||||
|
||||
- 当用户提交的任务参数无效时会发生什么(例如,缺少必填字段)?系统应在创建任务之前进行验证。
|
||||
- 当用户在任务处理时关闭浏览器会发生什么?任务数据保存在浏览器本地存储中,当用户返回时从本地存储恢复。
|
||||
- 当任务处理时间异常长时会发生什么?图片生成任务在 10 分钟后超时,视频生成任务在 30 分钟后超时,超时任务被标记为失败。
|
||||
- 当多个用户共享同一账户并提交任务时会发生什么?每个用户应看到账户的所有任务,或根据身份验证使任务特定于用户。
|
||||
- 当生成的内容保存失败时会发生什么?系统应重试保存操作,如果保存继续失败则将任务标记为失败。
|
||||
- 当用户在队列中有任务时导航离开页面会发生什么?任务通过浏览器本地存储在页面导航之间持久保存。
|
||||
- 当后台生成服务完全不可用时会发生什么?系统使用指数退避策略自动重试(1分钟、5分钟、15分钟),超过3次重试后标记任务为失败。
|
||||
- 当用户清除浏览器数据或使用隐私模式时会发生什么?用户将丢失所有任务历史记录和队列数据。
|
||||
|
||||
## 需求 *(必填)*
|
||||
|
||||
### 功能需求
|
||||
|
||||
- **FR-001**: 系统必须在用户为图片或视频内容点击"生成"时创建后台任务
|
||||
- **FR-002**: 系统必须在任务创建后立即将生成表单重置为初始状态
|
||||
- **FR-003**: 系统必须允许用户在先前任务处理时提交新的生成任务
|
||||
- **FR-004**: 系统必须在页面底部显示固定工具栏,显示任务摘要(例如:生成中任务数量、最新状态)
|
||||
- **FR-005**: 系统必须允许用户点击底部工具栏展开完整的任务队列面板
|
||||
- **FR-006**: 系统必须在展开的任务队列面板中显示所有用户提交的任务,不设置队列容量上限
|
||||
- **FR-007**: 系统必须跟踪任务状态,至少包括:待处理、处理中、重试中、已完成和失败状态
|
||||
- **FR-008**: 系统必须在生成进度推进时实时或近实时更新任务状态
|
||||
- **FR-009**: 系统必须使用浏览器本地存储(LocalStorage 或 IndexedDB)在页面刷新和浏览器会话之间持久保存任务数据
|
||||
- **FR-010**: 系统必须为已完成的任务提供对生成内容的访问
|
||||
- **FR-011**: 系统必须为失败的任务显示错误信息,帮助用户了解出了什么问题
|
||||
- **FR-012**: 系统必须支持图片和视频生成任务类型
|
||||
- **FR-013**: 系统必须在后台异步处理任务,不阻塞用户界面
|
||||
- **FR-014**: 系统必须保留任务参数(提示词、设置等)以供参考和可能的重试
|
||||
- **FR-015**: 系统必须允许用户取消待处理或处理中的任务
|
||||
- **FR-016**: 系统必须在短时间窗口内(可配置,例如 5 秒)防止相同参数的重复任务提交
|
||||
- **FR-017**: 系统必须优雅地处理任务失败,并允许用户使用相同参数重试失败的任务
|
||||
- **FR-018**: 系统必须在后台生成服务不可用或超时时实施指数退避重试策略,重试间隔为 1 分钟、5 分钟、15 分钟,最多重试 3 次
|
||||
- **FR-019**: 系统必须在任务详情中显示重试计数和下次重试时间(如适用)
|
||||
- **FR-020**: 系统必须在达到最大重试次数后将任务标记为失败,并提供清晰的错误消息
|
||||
- **FR-021**: 系统必须为图片生成任务设置 10 分钟的超时限制,超过此时间将任务标记为失败
|
||||
- **FR-022**: 系统必须为视频生成任务设置 30 分钟的超时限制,超过此时间将任务标记为失败
|
||||
- **FR-023**: 系统必须在任务超时时显示明确的超时错误消息,区分于其他类型的失败
|
||||
- **FR-024**: 系统必须在应用加载时从浏览器本地存储读取任务队列并恢复所有任务状态
|
||||
- **FR-025**: 系统必须在每次任务状态变化时更新浏览器本地存储以确保数据一致性
|
||||
- **FR-026**: 系统必须在底部工具栏任务摘要中显示关键信息,包括:生成中任务数量、已完成任务数量、失败任务数量
|
||||
- **FR-027**: 系统必须允许用户收起展开的任务队列面板,返回到仅显示摘要的状态
|
||||
|
||||
### 关键实体
|
||||
|
||||
- **生成任务**: 表示单个内容生成请求,包含任务 ID、任务类型(图片/视频)、提交时间戳、状态、生成参数(提示词、设置)、结果引用(URL 或标识符)、错误消息(如果失败)、重试计数、下次重试时间、超时限制(图片 10 分钟,视频 30 分钟)和用户标识符等属性,存储在浏览器本地存储中
|
||||
- **任务队列**: 用户所有生成任务的集合,按提交时间或优先级排序,具有按状态筛选的能力,无容量限制,持久化在浏览器本地存储中
|
||||
- **生成内容**: 已完成任务产生的输出工件(图片或视频文件),包含创建时间戳、文件大小、格式以及指向源任务链接等元数据
|
||||
- **任务工具栏**: 页面底部固定的UI组件,显示任务摘要和快速访问入口,可展开显示完整队列面板
|
||||
|
||||
## 成功标准 *(必填)*
|
||||
|
||||
### 可衡量的成果
|
||||
|
||||
- **SC-001**: 用户可以在点击上一个任务的"生成"后 2 秒内提交新的生成任务
|
||||
- **SC-002**: 表单在任务提交后 500 毫秒内重置为初始状态
|
||||
- **SC-003**: 任务队列显示所有任务的当前状态,更新在状态变化后 5 秒内出现
|
||||
- **SC-004**: 用户可以快速连续成功提交和排队至少 10 个生成任务,无错误
|
||||
- **SC-005**: 95% 的用户可以在任务完成后 10 秒内找到并访问其生成的内容
|
||||
- **SC-006**: 任务队列在浏览器会话之间从本地存储持久保存,任务状态和参数 100% 准确
|
||||
- **SC-007**: 用户可以在 2 秒内完成任务管理操作(取消、重试、清除)
|
||||
- **SC-008**: 系统处理并发任务,支持至少 5 个同时用户生成内容,性能无下降
|
||||
- **SC-009**: 当后台服务临时不可用时,90% 的任务在自动重试后成功完成,无需用户干预
|
||||
- **SC-010**: 系统能够处理每个用户超过 100 个任务的队列,界面响应时间保持在 2 秒内
|
||||
- **SC-011**: 图片生成任务在 10 分钟内完成或被标记为超时失败,准确率 100%
|
||||
- **SC-012**: 视频生成任务在 30 分钟内完成或被标记为超时失败,准确率 100%
|
||||
- **SC-013**: 应用加载时从本地存储恢复任务队列的时间不超过 1 秒
|
||||
- **SC-014**: 底部工具栏任务摘要在 200 毫秒内响应用户点击并展开队列面板
|
||||
- **SC-015**: 队列面板展开/收起动画流畅,帧率保持在 60 FPS
|
||||
1376
specs/001-batch-task-queue/tasks.md
Normal file
1376
specs/001-batch-task-queue/tasks.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user