[M-AI-02-04] Expand AiAnalysisJob 生命周期、执行与输出字段 #276

Closed
opened 2026-06-19 23:30:04 +08:00 by wangdl · 1 comment
Owner

依赖

  • M-AI-02-03

目标

增加统一生命周期、执行控制、输出版本和错误字段,但不切换现有读取逻辑。

范围

按 ADR 增加:

lifecycleStatus
credentialMode
credentialId
modelTier
promptKey
promptVersion
outputSchemaVersion
progress
attemptCount
maxAttempts
timeoutMs
validatedOutput
outputHash
errorCode
publicErrorMessage
internalErrorMessage
queuedAt
startedAt
finishedAt
cancelRequestedAt

新增生命周期 enum:

created
queued
running
retrying
succeeded
failed
cancel_requested
cancelled

约束

  • lifecycleStatus 初始允许为空;
  • status 字段和 enum 保留;
  • 现有业务仍读取旧 status
  • 不得自动将旧 API 返回值改为新状态;
  • 不得在本 Issue 回填历史数据;
  • 不得修改 Worker 状态机。

验收

  • 旧数据全部可读;
  • 旧应用版本可启动;
  • 新字段没有造成已有 INSERT 失败;
  • JSON 字段大小和数据库类型符合 ADR;
  • 错误字段区分公开错误与内部错误;
  • 无敏感信息进入公开错误字段。
## 依赖 * M-AI-02-03 ## 目标 增加统一生命周期、执行控制、输出版本和错误字段,但不切换现有读取逻辑。 ## 范围 按 ADR 增加: ``` lifecycleStatus credentialMode credentialId modelTier promptKey promptVersion outputSchemaVersion progress attemptCount maxAttempts timeoutMs validatedOutput outputHash errorCode publicErrorMessage internalErrorMessage queuedAt startedAt finishedAt cancelRequestedAt ``` 新增生命周期 enum: ``` created queued running retrying succeeded failed cancel_requested cancelled ``` ## 约束 * `lifecycleStatus` 初始允许为空; * 旧 `status` 字段和 enum 保留; * 现有业务仍读取旧 `status`; * 不得自动将旧 API 返回值改为新状态; * 不得在本 Issue 回填历史数据; * 不得修改 Worker 状态机。 ## 验收 * 旧数据全部可读; * 旧应用版本可启动; * 新字段没有造成已有 INSERT 失败; * JSON 字段大小和数据库类型符合 ADR; * 错误字段区分公开错误与内部错误; * 无敏感信息进入公开错误字段。
wangdl added this to the M-AI-02 统一 AiJob 数据库 Expand milestone 2026-06-19 23:30:04 +08:00
wangdl added the
area:database
type:migration
backend
prisma
labels 2026-06-19 23:30:04 +08:00
wangdl changed title from [M-AI-02] Expand AiAnalysisJob 生命周期、执行与输出字段 to [M-AI-02-04] Expand AiAnalysisJob 生命周期、执行与输出字段 2026-06-19 23:31:04 +08:00
Author
Owner

开发完成评论

完成内容

  • 新增 20 个字段:lifecycleStatuslockedBylockedAtlockUntilcancelRequestedAtattemptCountmaxAttemptstimeoutMscredentialModecredentialIdmodelTiermodelProvidermodelNamepromptKeypromptVersionoutputSchemaVersionoutputHashvalidatedOutputerrorCodepublicErrorMessage
  • 2 处列重命名:errorMessageinternalErrorMessagecompletedAtfinishedAt
  • 2 个新索引:(lifecycleStatus, createdAt)(queueName, lifecycleStatus, createdAt)
  • 源码更新:ai-analysis.repository.ts + ai-analysis.service.ts 适配新字段名(API JSON key 保持不变)

Migration SQL 审查

  • 无 DROP TABLE/DROP COLUMN
  • 所有新列 nullable 或有 safe default
  • lifecycleStatus 初始 NULL(符合约束)
  • internalErrorMessage 为 TEXT NULL(保留旧数据)
  • finishedAt 为 DATETIME NULL(保留旧数据)
  • validatedOutput 为 JSON(MySQL 原生类型,无大小上限)
  • 公开错误 publicErrorMessage VARCHAR(500) 与内部错误 internalErrorMessage TEXT 分离
  • 无整表重建

修改文件

  • prisma/schema.prisma:AiAnalysisJob model 新增 20 字段 + 2 索引
  • prisma/migrations/20260620000001_m_ai_02_04_lifecycle_execution/migration.sql(新增)
  • src/modules/ai-analysis/ai-analysis.repository.ts:23-25completedAtfinishedAterrorMessageinternalErrorMessage
  • src/modules/ai-analysis/ai-analysis.service.ts:63-64:Prisma 字段访问适配(API JSON key 保持 completedAt/errorMessage 向后兼容)

验证

  • Row count: 9 → 9
  • 22 new/renamed columns verified
  • Defaults applied (all 9 rows): credentialMode=platform_key, modelTier=primary, modelProvider=deepseek, modelName=deepseek-chat, attemptCount=0, maxAttempts=3, timeoutMs=120000
  • Old data preserved: finishedAt/internalErrorMessage correctly carry over from completedAt/errorMessage
  • 2 new indexes

测试情况

  • 已运行:npx jest --testPathPatterns="ai-analysis|ai-runtime|active-recall|feynman" --passWithNoTests
  • 结果:11 suites, 265 tests passed

未完成 / 风险

  • lifecycleStatus 当前全部为 NULL,M-AI-02-10 回填
  • status 列保留,现有业务仍读取旧状态

是否建议进入 Review

## 开发完成评论 ### 完成内容 - 新增 20 个字段:`lifecycleStatus`、`lockedBy`、`lockedAt`、`lockUntil`、`cancelRequestedAt`、`attemptCount`、`maxAttempts`、`timeoutMs`、`credentialMode`、`credentialId`、`modelTier`、`modelProvider`、`modelName`、`promptKey`、`promptVersion`、`outputSchemaVersion`、`outputHash`、`validatedOutput`、`errorCode`、`publicErrorMessage` - 2 处列重命名:`errorMessage` → `internalErrorMessage`、`completedAt` → `finishedAt` - 2 个新索引:`(lifecycleStatus, createdAt)`、`(queueName, lifecycleStatus, createdAt)` - 源码更新:`ai-analysis.repository.ts` + `ai-analysis.service.ts` 适配新字段名(API JSON key 保持不变) ### Migration SQL 审查 - ✅ 无 DROP TABLE/DROP COLUMN - ✅ 所有新列 nullable 或有 safe default - ✅ `lifecycleStatus` 初始 NULL(符合约束) - ✅ `internalErrorMessage` 为 TEXT NULL(保留旧数据) - ✅ `finishedAt` 为 DATETIME NULL(保留旧数据) - ✅ `validatedOutput` 为 JSON(MySQL 原生类型,无大小上限) - ✅ 公开错误 `publicErrorMessage` VARCHAR(500) 与内部错误 `internalErrorMessage` TEXT 分离 - ✅ 无整表重建 ### 修改文件 - `prisma/schema.prisma`:AiAnalysisJob model 新增 20 字段 + 2 索引 - `prisma/migrations/20260620000001_m_ai_02_04_lifecycle_execution/migration.sql`(新增) - `src/modules/ai-analysis/ai-analysis.repository.ts:23-25`:`completedAt` → `finishedAt`、`errorMessage` → `internalErrorMessage` - `src/modules/ai-analysis/ai-analysis.service.ts:63-64`:Prisma 字段访问适配(API JSON key 保持 `completedAt`/`errorMessage` 向后兼容) ### 验证 - Row count: 9 → 9 ✅ - 22 new/renamed columns verified ✅ - Defaults applied (all 9 rows): credentialMode=`platform_key`, modelTier=`primary`, modelProvider=`deepseek`, modelName=`deepseek-chat`, attemptCount=`0`, maxAttempts=`3`, timeoutMs=`120000` ✅ - Old data preserved: `finishedAt`/`internalErrorMessage` correctly carry over from `completedAt`/`errorMessage` ✅ - 2 new indexes ✅ ### 测试情况 - 已运行:`npx jest --testPathPatterns="ai-analysis|ai-runtime|active-recall|feynman" --passWithNoTests` - 结果:11 suites, 265 tests passed ### 未完成 / 风险 - `lifecycleStatus` 当前全部为 NULL,M-AI-02-10 回填 - 旧 `status` 列保留,现有业务仍读取旧状态 ### 是否建议进入 Review - 是
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wangdl/api-server#276
No description provided.