为 FastGPT 新增、修改或审查自动系统升级脚本及其注册信息。涉及系统迁移、升级任务、启动迁移、migration registry、checkpoint、全量重跑、阻塞升级、进度或失败数据时使用;普通业务更新和未接入自动升级框架的一次性手工清洗不使用。
72
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
系统升级任务属于 App 部署生命周期能力。框架负责顺序、状态、lease、并发互斥、重试入口和最终状态;脚本只负责可重复执行的业务迁移、进度、checkpoint,以及与阻塞类型匹配的错误报告方式。
开始前先查看当前实现,不能凭本 Skill 猜测已经变化的 Context 或目录结构:
projects/app/src/migration/registry.tsprojects/app/src/migration/runner.tspackages/global/migration/constants.tspackages/global/migration/schema.tsprojects/app/src/migration/tasks/README.md如果这些路径正在迁移,以仓库中 systemMigrations 和 SystemMigrationContext 的实际定义为准。迁移执行框架和任务实现收敛到 projects/app/src/migration;需要被 App 前后端共同使用的状态枚举、Zod Schema 和 API 类型放在 packages/global/migration。
先明确以下契约;存在会改变数据安全或启动行为的缺失信息时,向用户确认后再编码:
YYYYMMDD_short_semantic_name,以及首次发布版本。$setOnInsert、compare-and-set 或事务性全量重建。不要用“目标表存在”“目标表非空”或当前数据形态替代任务状态。是否需要执行只能由静态注册表和迁移状态决定。
blockStartup、onFailure 和函数语义不得修改、删除或复用;修复已发布迁移时追加新任务。| 状态 | 谁负责写入 | 触发条件 |
|---|---|---|
pending | 框架 | 首次初始化,或管理员将非阻塞失败任务恢复为待执行 |
running | Runner | 原子获得 lease,并生成新的 runId |
failed | Runner / context.fail | 脚本明确报告失败,或普通异常被 Runner 捕获 |
succeeded | Runner | 脚本正常返回且当前 runId 仍持有有效 lease |
脚本禁止直接操作迁移状态表和错误数据表,也不得主动设置 pending、running、failed 或 succeeded。所有运行状态写入必须经过 Context,让框架统一执行 runId fencing 和输入校验。
context.reportProgress(...):按注册表声明的阶段 key 更新该阶段快照。进入阶段时上报 running,完成后上报 succeeded;分批任务按合理频率更新 current/total,不要每条数据写一次。脚本不得主动上报 failed。context.getCheckpoint(schema):读取并用任务自有 Zod Schema 校验断点。仅分批任务使用。context.getFailedRecords():仅供非阻塞任务读取上次失败留下的坏数据。若任务曾跳过坏数据并把 checkpoint 推进到其后,重试时必须先处理这些记录;阻塞任务调用会被 Context 拒绝。context.reportFailedRecords(records):仅供非阻塞任务按批替换“当前完整未解决错误快照”。业务批次提交后应先上报错误快照,再推进 checkpoint;替换语义保证批次重放不会重复追加同一错误。阻塞任务调用会被 Context 拒绝。context.saveCheckpoint(value):只在一个幂等批次的业务事务完整提交、错误快照成功持久化并校验后保存。禁止先保存 checkpoint 再写业务数据或上报该批错误。context.assertActive():确认当前 runId 仍持有 lease。每个业务写入批次前必须调用;全量任务至少在关键事务前及事务后的后续阶段前调用。context.fail(...):保存可预期的结构化错误及最终错误快照,并终止本次执行。主要供需要在管理页面排障和重试的非阻塞任务使用;不要在调用后继续业务逻辑。阻塞任务通过该方法携带 failedRecords 会被拒绝。context.logger:记录诊断信息,框架会附加 migrationId、runId 和 runnerId。日志不能替代进度或结构化失败。context.signal:长计算或可取消 I/O 应响应中止信号。正常返回表示脚本认为业务迁移和完成校验均已成功,由 Runner 标记 succeeded 并清理该任务的错误明细。任务可以返回有限标量的业务参数对象;Runner 校验后把参数与 succeeded 原子写入,列表接口再从静态注册表取得 resultKey 组装展示结果。nameKey、descriptionKey、resultKey 和阶段 labelKey 必须在注册表中使用 i18nT(...) 声明,禁止把 i18n key 写入 Mongo。不要自行调用完成状态更新,也不要用最后一条 progress 代替最终结果。
普通 throw 也会进入 failed,Runner 会把错误归属到当前 running 阶段,并保留任务之前通过 reportFailedRecords 上报的最新快照。只有 context.fail 显式携带 failedRecords(包括空数组)时才替换或清空旧快照。非阻塞任务的已知数据问题应维护完整未解决错误快照:处理中按批调用 context.reportFailedRecords,扫描结束仍有异常时再调用 context.fail 写入相同最终快照。错误对象只保存原始 message,不得携带 i18n key 或模板参数;每条错误数据必须包含已声明的 stageKey,只保存必要 ID 和原因,不复制原文档。框架按阶段记录异常数量,管理员从对应阶段按需打开详情。阻塞任务失败时管理页面本身不可用,应通过 context.logger 输出必要诊断后抛出异常;Context 会拒绝其读写错误明细,Runner 只把多节点协调所需的最小 lastError 写入状态表。
任务一旦获得新 runId,无论入口是管理员重置还是过期 lease 接管,都使用同一恢复策略:保留 checkpoint、progress 和最近错误;非阻塞任务还会保留供修复使用的错误明细。但触发条件不同:running 的 lease 过期可自动接管,阻塞 failed 在 owner 重启、lease 过期后可接管,非阻塞 failed 必须由管理员重置为 pending。脚本如何恢复由发布时选定的策略决定。
适用于数据量较大、执行时间不可控、无法在一个短事务内完成,或需要跳过坏数据继续扫描的任务。
每次执行必须覆盖三种输入状态:
推荐循环:
读取并校验 checkpoint
读取 failedRecords,建立完整未解决错误快照并优先重试
while 还有数据:
assertActive
按稳定游标读取下一批
在业务事务中执行幂等写入
校验该批结果并提交事务
如果错误快照变化,reportFailedRecords(完整未解决错误快照)
saveCheckpoint
reportProgress
执行全局完成校验
如果仍有错误,fail(包含相同最终错误快照)
reportProgress(completed)
return关键约束:
_id 或其他不可变、唯一且有索引的游标;不要使用 offset。reportFailedRecords 接收的是完整快照而不是新增项;不得逐条 append,也不得只上报当前批次,否则会覆盖之前仍未解决的错误。context.fail({ failedRecords }),其中 failedRecords 与最近一次上报的完整快照一致。仅适用于数据量确定较小、资源消耗有上界、结果由权威源确定,且整次写入可以保持原子或安全幂等的任务。
推荐流程:
reportProgress(started)
读取完整权威源
在修改目标前完成全部转换、去重和校验
assertActive
原子写入或确定性覆盖完整结果
assertActive
刷新缓存并执行完成校验
reportProgress(completed)
return关键约束:
blockStartup 只决定节点 readiness,onFailure 只决定失败后是否暂停后续队列;所有任务仍严格按注册表顺序单线程执行。
reportProgress 保存最新快照并同步输出阶段日志;具体错误诊断写终端日志,不写 failedRecords。状态表中的最小 lastError 仅用于跨节点观察失败事实,不承担错误日志存储职责。onFailure: 'continue' 只允许相互独立的非阻塞任务使用:当前任务保持 failed 且等待管理员重试,Runner 可以跳过它继续后续任务;stop 则暂停后续队列。onFailure: 'stop' 的非阻塞任务仍是启动前置条件;continue 任务失败后允许后续阻塞任务推进,因此必须确认二者没有成功依赖。迁移执行框架、静态注册表、Mongo Schema、服务端执行逻辑和任务集中在 App;前后端公共契约位于 global:
packages/global/migration/
├── constants.ts
└── schema.ts
projects/app/src/migration/
├── constants.ts
├── registry.ts
├── runner.ts
├── entity.ts
├── service.ts
├── mongoSchema.ts
├── utils.ts
└── tasks/
├── README.md
└── <migration-id>/
├── index.ts
├── service.ts
└── utils.tsindex.ts 只负责任务编排、Context 调用和进度阶段。packages/global/migration 只保存前后端共享的状态枚举、有限输入 Schema 和 API 类型,不放任务实现、Mongo Model 或 Runner。progressSteps: [{ key, labelKey }];key 是永久稳定的机器标识,labelKey 放在 client-only system_migration i18n namespace,不写入 Mongo。packages/global 或 packages/service。pages/api、pages/config,但必须是调用 migration service 的薄入口,不承载迁移逻辑。i18nT(...) 保存稳定的 name、description、result 和 progress label key。message。projects/app/test/migration/ 下并镜像源码子路径。新增任务至少验证与其恢复策略相关的真实不变量,不写只匹配文案的测试。
通用场景:
running -> succeeded 上报;任务返回前所有声明阶段都已成功,阶段异常和错误数据使用正确的 stageKey。blockStartup 和 onFailure 符合数据依赖。分批任务额外验证:
getFailedRecords、reportFailedRecords 或通过 fail 携带 failedRecords 时会被 Context 拒绝。全量任务额外验证:
只运行覆盖改动范围的局部测试、App typecheck、相关 ESLint 和 git diff --check。用户最终验收前不主动运行全量测试。若修改 API 路由或入参,继续遵守 api-development Skill;若新增单元测试,继续遵守 test-case Skill。
lastError,没有调用错误明细能力。42512fa
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.