Skip to main content

system-migration-development

为 FastGPT 新增、修改或审查自动系统升级脚本及其注册信息。涉及系统迁移、升级任务、启动迁移、migration registry、checkpoint、全量重跑、独立模式、进度或失败数据时使用;普通业务更新和未接入自动升级框架的一次性手工清洗不使用。

소스 정보

저장소
labring/FastGPT
최근 소스 활동
2026년 10월 26일 16:25
감지된 SKILL.md 언어
중국어
스타
29,943
포크
7,351

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
system-migration-development
description
为 FastGPT 新增、修改或审查自动系统升级脚本及其注册信息。涉及系统迁移、升级任务、启动迁移、migration registry、checkpoint、全量重跑、独立模式、进度或失败数据时使用;普通业务更新和未接入自动升级框架的一次性手工清洗不使用。
# FastGPT 系统升级脚本开发规范 ## 目标与边界 系统升级任务属于 App 部署生命周期能力。框架负责顺序、状态、每任务 lease 互斥、启动依赖链、后台普通队列与独立任务调度、重试入口和最终状态;脚本只负责可重复执行的业务迁移、进度、checkpoint,以及结构化错误报告。 开始前先查看当前实现,不能凭本 Skill 猜测已经变化的 Context 或目录结构: - `projects/app/src/migration/registry.ts` - `projects/app/src/migration/runner.ts` - `projects/app/src/migration/plan.ts` - `projects/app/src/migration/startup.ts` - `packages/global/migration/constants.ts` - `packages/global/migration/schema.ts` - `projects/app/src/migration/tasks/README.md` - 注册表中最近一个任务及其测试 如果这些路径正在迁移,以仓库中 `systemMigrations` 和 `SystemMigrationContext` 的实际定义为准。迁移执行框架和任务实现收敛到 `projects/app/src/migration`;需要被 App 前后端共同使用的状态枚举、Zod Schema 和 API 类型放在 `packages/global/migration`。 ## 编写前必须确认 先明确以下契约;存在会改变数据安全或启动行为的缺失信息时,向用户确认后再编码: 1. 永久稳定的任务 ID,格式为 `YYYYMMDD_short_semantic_name`,以及首次发布版本(对应版本目录去除点号,例如版本 `4.17.0` 对应目录 `4170`,`4.17.1` 对应 `4171`)。 2. 源数据、目标数据、权威数据源和迁移完成条件。 3. 该任务为什么必须排在当前注册表末尾,以及它依赖哪些前置任务。 4. 选择启动阻塞、普通自动、延迟自动、手动触发或独立模式;显式声明所有真实的成功前置。启动阻塞任务及其完整依赖链必须在 App 业务启动前成功;后台失败只影响自身与依赖它的任务,后台独立任务必须不依赖其他迁移且允许并发执行。 5. 恢复策略是“分批断点续跑”还是“幂等全量重跑”。该策略发布后不能切换。 6. 重复执行的幂等依据:唯一键、确定性覆盖、`$setOnInsert`、compare-and-set 或事务性全量重建。 7. 数据规模、预期耗时、批次大小和内存上界。 8. 坏数据是立即终止,还是跳过、汇总后由管理员修复再重试。 9. 滚动升级期间,旧版本节点是否仍能安全读写迁移中的结构。 10. 成功校验、失败回滚方式,以及需要展示给管理员的进度和错误定位数据。 不要用“目标表存在”“目标表非空”或当前数据形态替代任务状态。是否需要执行只能由静态注册表和迁移状态决定。 ## 基本要求 - 注册表只允许在数组尾部追加。已发布任务的 ID、顺序、调度模式、依赖和函数语义不得修改、删除或复用;修复已发布迁移时追加新任务。 - 完整任务及其可能重放的最小单元必须幂等。Lease 只保证同一时刻的执行权,不提供 exactly-once。 - 默认追加或回填,不删除旧字段、旧集合、回滚依据或用户数据。破坏性清理应放到后续兼容窗口结束后的独立任务。 - 自动迁移必须兼容滚动升级;要求全站停机或会立即破坏旧版本的变更不能直接进入该注册表。 - 禁止不可重放的外部副作用,例如无幂等键的消息、扣费或第三方写入。 - 所有业务写入必须有确定性,不能根据不稳定排序、offset 分页或随机值决定结果。 - 修改目标前验证源数据;返回前校验完成条件。不能仅因函数没有抛错就假设迁移完成。 - 日志、进度、最终结果、checkpoint 和错误数据不得包含凭证、完整业务正文、超大对象或完整错误栈。 - 迁移专属实现不得放入业务 DDD 模块。业务模块可以被迁移单向依赖,但不能反向依赖迁移目录。 ## 状态与 Context ### 状态所有权 | 状态 | 谁负责写入 | 触发条件 | | --- | --- | --- | | `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.reportFailedRecords(records)`:按批替换“当前完整未解决错误快照”。业务批次提交后应先上报错误快照,再推进 checkpoint;替换语义保证批次重放不会重复追加同一错误。 - `context.saveCheckpoint(value)`:只在一个幂等批次的业务事务完整提交、错误快照成功持久化并校验后保存。禁止先保存 checkpoint 再写业务数据或上报该批错误。 - `context.assertActive()`:确认当前 `runId` 仍持有 lease。每个业务写入批次前必须调用;全量任务至少在关键事务前及事务后的后续阶段前调用。 - `context.fail(...)`:保存可预期的结构化错误及最终错误快照,并终止本次执行。供需要在管理页面排障和重试的任务使用;不要在调用后继续业务逻辑。 - `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 和原因,不复制原文档。框架按阶段记录异常数量,管理员从对应阶段按需打开详情。后台任务失败后停止 heartbeat,管理员修复后通过页面重试。启动链失败后持续续租,页面不可用,通过日志定位并修复,重启 lease owner 后等待过期接管;独立前置提升为启动任务后同样遵守此规则。 ## 选择恢复策略 任务一旦获得新 runId,无论入口是管理员重置还是过期 lease 接管,都使用同一恢复策略:保留 checkpoint、progress 和最近错误;任务还会保留供修复使用的错误明细。但触发条件不同:后台只有 `running` 的 lease 过期可自动接管,`failed` 必须由管理员重置为 `pending`。启动链的 `failed` 由存活 owner 持续续租;修复并重启该 owner 后,过期 failed 允许原子接管,不允许在线重置。脚本如何恢复由发布时选定的策略决定。 ### 分批断点续跑 适用于数据量较大、执行时间不可控、无法在一个短事务内完成,或需要跳过坏数据继续扫描的任务。 每次执行必须覆盖三种输入状态: 1. 无 checkpoint、无错误数据:从稳定排序的起点开始。 2. 有 checkpoint、无错误数据:从最后完整提交的批次之后继续。 3. 有 checkpoint、有错误数据:先重新处理已跳过的错误记录,再从 checkpoint 继续扫描新数据。 推荐循环: ```text 读取并校验 checkpoint 读取 failedRecords,建立完整未解决错误快照并优先重试 while 还有数据: assertActive 按稳定游标读取下一批 在业务事务中执行幂等写入 校验该批结果并提交事务 如果错误快照变化,reportFailedRecords(完整未解决错误快照) saveCheckpoint reportProgress 执行全局完成校验 如果仍有错误,fail(包含相同最终错误快照) reportProgress(completed) return ``` 关键约束: - 使用 `_id` 或其他不可变、唯一且有索引的游标;不要使用 offset。 - 进程可能在业务提交后、checkpoint 保存前退出,因此整个批次必须可重复执行。 - checkpoint 只记录恢复所需的最小游标,不保存业务正文或不断增长的数组。 - `reportFailedRecords` 接收的是完整快照而不是新增项;不得逐条 append,也不得只上报当前批次,否则会覆盖之前仍未解决的错误。 - 错误快照必须先于对应 checkpoint 持久化。若进程在两者之间退出,接管节点会从旧 checkpoint 重放该批,并能读取已经保存的错误;禁止反向调用造成坏数据被 checkpoint 永久跳过。 - 错误快照已上报后又发生未预期异常时,Runner 会保留该快照;任务不得为了上报新异常而传入不完整的错误数组。 - 扫描结束仍有失败项时调用 `context.fail({ failedRecords })`,其中 `failedRecords` 与最近一次上报的完整快照一致。 - 重试后再次失败会替换旧错误明细;完整成功后由框架删除。 ### 幂等全量重跑 仅适用于数据量确定较小、资源消耗有上界、结果由权威源确定,且整次写入可以保持原子或安全幂等的任务。 推荐流程: ```text reportProgress(started) 读取完整权威源 在修改目标前完成全部转换、去重和校验 assertActive 原子写入或确定性覆盖完整结果 assertActive 刷新缓存并执行完成校验 reportProgress(completed) return ``` 关键约束: - 不保存没有恢复意义的伪 checkpoint。每次管理员重试或 lease 接管都重新执行完整流程。 - 如果需要清空目标,目标必须完全由权威源派生,不包含用户增量;权威源必须保留。 - 清空和完整重建必须在同一事务中,失败时不能暴露空表或半成品。 - 源数据必须在清空目标前完成校验;重复执行和源数据修复后再执行都应产生确定结果。 - 如果全量操作无法在 lease 内稳定完成,改用分批策略,而不是单纯调大 lease。 ## 执行模式与失败调度 `plan.ts` 校验注册表,递归收集所有 `blockStartup: true` 根任务与其 `dependsOn` 闭包。依赖只允许引用更早注册的任务,闭包按原注册顺序串行执行,跳过无关任务;独立前置被提升后不竞争后台 Redis 名额。启动链不得包含 manual 或 delay,根任务不能同时声明 independent。 所有节点等待完整启动链持久化为 succeeded,缺失、读取异常、pending、running、failed 都不放行。随后每个节点重载本地模型缓存、启动业务消费者,最后启用后台迁移。共享状态成功不能代替跟随节点的缓存重载;App 屏障不停止旧版本节点或独立 Pro 服务,仍需证明滚动升级兼容。 - 启动阻塞:`blockStartup: true`,自身及递归前置成功前阻塞 App readiness。当前仅旧系统模型迁移声明该模式。 - 普通自动:启动链成功后进入普通队列,按注册顺序串行执行。 - 延迟自动:`delay: true`,获得 lease 后等待 SYSTEM_MIGRATION_DELAY_SECONDS 秒,默认 0,期间占用后台普通队列。 - 手动触发:`manual: true`,初始 waiting;管理员确认前提后入队,随后使用后台普通队列。不能与 delay 或 independent 同时启用,也不能出现在启动闭包中。 - 独立执行:`independent: true`,启动链完成后每个任务单独调度,不受后台普通队列顺序约束;所有节点通过 Redis LeaseCache.withConcurrency 共享 3 个名额,先取得名额再竞争任务 Mongo lease。不能与 blockStartup、manual、delay 或非空 dependsOn 同时启用。 - `dependsOn` 只能引用更早注册的任务。普通任务可依赖独立任务;所有前置成功前不得执行。被启动链引用的前置统一提升,列表 DTO 返回有效 blockStartup=true、independent=false。 - 后台失败不暂停整个队列,不提供 onFailure 或 stop/continue 配置。成功前提必须通过 dependsOn 声明,不能用相邻顺序代替依赖,也不能把无关任务串成依赖链。 - 启动链失败保持续租,日志记录错误原因和 migrationId/runId/runnerId;修复并重启 lease owner,过期后由一个节点接管。其他节点保持未就绪,后台不能执行。后台明确失败停止续租并等待管理员重试。 - 所有任务均可报告结构化失败明细、保存恢复数据。独立模式必须证明数据与其他后台任务互不依赖且资源消耗允许并发;App ready 只保证启动链成功,不表示后台回填完成。 ## 文件位置 迁移执行框架、静态注册表、Mongo Schema、服务端执行逻辑和任务集中在 App;前后端公共契约位于 global: ```text packages/global/migration/ ├── constants.ts └── schema.ts projects/app/src/migration/ ├── constants.ts ├── registry.ts ├── plan.ts ├── startup.ts ├── runner.ts ├── entity.ts ├── service.ts ├── mongoSchema.ts ├── utils.ts └── tasks/ ├── README.md └── <version>/ └── <migration-id>/ ├── index.ts ├── service.ts └── utils.ts ``` - `index.ts` 只负责任务编排、Context 调用和进度阶段。 - 迁移任务必须按 `tasks/<version>/<migration-id>/` 目录规范定义,严禁在 `tasks/` 根目录下平铺存放迁移脚本。其中 `<version>` 对应发布版本(无点号,如 `4.17.0` 对应 `4170`,`4.17.1` 对应 `4171`),`<migration-id>` 为具体迁移任务 ID。 - 同一版本内多个迁移任务共享的辅助逻辑、类型或转换工具,应收敛在该版本的公共子目录内(例如 `tasks/<version>/<shared_helper_dir>/`),严禁在 `tasks/` 根目录下平铺。 - `packages/global/migration` 只保存前后端共享的状态枚举、有限输入 Schema 和 API 类型,不放任务实现、Mongo Model 或 Runner。 - 注册项必须按执行顺序声明完整的 `progressSteps: [{ key, labelKey }]`;`key` 是永久稳定的机器标识,`labelKey` 放在 client-only `system_migration` i18n namespace,不写入 Mongo。 - 该任务专属的数据访问、转换和工具函数全部放在同名目录,不要散落到 `packages/global` 或 `packages/service`。 - 真正被正常运行期业务复用的能力保留在业务模块;迁移通过单向依赖调用它。 - Next.js API 路由和页面受框架目录约束,可以保留在 `pages/api`、`pages/admin`,但必须是调用 migration service 的薄入口,不承载迁移逻辑。 - i18n 文案按项目现有机制放入所有语言文件;任务注册项使用 `i18nT(...)` 保存稳定的 name、description、result 和 progress label key。 - i18n key 只属于静态注册表和 API 展示 DTO,禁止写入状态表或错误明细表。成功结果只持久化有限标量参数,错误只持久化原始 `message`。 - 测试放在 `projects/app/test/migration/` 下并严格镜像源码子路径(即 `projects/app/test/migration/tasks/<version>/<migration-id>/`)。 ## 测试与验证 新增任务至少验证与其恢复策略相关的真实不变量,不写只匹配文案的测试。 通用场景: - 首次执行成功,完成条件真实成立。 - 重复执行不会产生重复、覆盖错误数据或改变不应变化的结果。 - 源数据无效时不会留下部分目标数据,并能给出可定位错误。 - 业务写入或完成校验失败时不会被标记成功。 - 进度阶段、失败记录和日志不包含敏感或无界数据。 - 每个阶段均按 `running -> succeeded` 上报;任务返回前所有声明阶段都已成功,阶段异常和错误数据使用正确的 `stageKey`。 - 最终结果只在任务成功后存在;Mongo 只含参数,列表接口从注册表补入 key 后能渲染出预期业务结果。 - 任务注册在数组尾部,ID 唯一,调度模式与显式前置依赖符合业务要求。 - 启动依赖闭包优先执行、共享前置不重复、独立前置提升、手动/延迟前置拒绝;每个节点先等待再重载模型,之后才启用业务与后台任务。 - 启动链 throw/context.fail 均持续续租并保持未就绪;owner 停止且 lease 过期后多节点只能一个接管,恢复数据保留;管理接口拒绝在线重试启动链。 分批任务额外验证: - 从 checkpoint 恢复,不重扫已完成范围。 - 业务提交后、checkpoint 前退出时,重复批次仍然正确。 - checkpoint 与错误记录同时存在时,错误记录会被重新处理。 - 错误快照会在每批后替换持久化,且崩溃发生在错误上报与 checkpoint 之间时不会丢失或重复追加坏数据。 - 错误快照之后发生普通异常时,已保存的坏数据不会被空数组覆盖。 - 中途丢失 lease 后不再开始新的业务批次或保存状态。 - 启动链成功后,独立任务不受后台普通队列长任务、延迟或失败影响;集群最多持有 3 个独立任务并发名额,排队任务不提前领取 Mongo lease;停止 Runner 时取消等待并通知全部活跃任务中止。 全量任务额外验证: - 目标已有旧数据时仍能完整覆盖为权威结果。 - 写入失败会回滚清空和部分写入。 - 修改权威源后再次运行会产生对应的新结果。 - 空源数据的行为经过明确设计和测试,不能默认为安全。 只运行覆盖改动范围的局部测试、App typecheck、相关 ESLint 和 `git diff --check`。用户最终验收前不主动运行全量测试。若修改 API 路由或入参,继续遵守 `api-development` Skill;若新增单元测试,继续遵守 `test-case` Skill。 ## 交付前检查 - [ ] 已确认恢复策略,并在任务函数注释中说明选择原因。 - [ ] 已证明任务整体及重放单元幂等。 - [ ] 只在注册表末尾追加,未修改已发布任务语义。 - [ ] 脚本未直接操作迁移状态表或错误数据表。 - [ ] 必需进度、lease 检查、完成校验和失败出口均已实现。 - [ ] 需要展示最终产出时已由任务返回有限的 i18n 结果,并由 Runner 随成功终态提交。 - [ ] checkpoint 保存时机正确,或全量任务明确不使用 checkpoint。 - [ ] 分批任务在 checkpoint 前及时替换完整错误快照,没有只在任务末尾一次性保存坏数据。 - [ ] 后台失败停止续租且可由管理员重试;启动失败保持续租,日志排障并重启 owner 后过期接管,业务与后台不提前放行。 - [ ] 启动依赖闭包、模式互斥、独立模式集群 3 个共享名额、Redis 故障不放行和租约丢失后的恢复已验证。 - [ ] 调度模式、显式依赖、滚动升级兼容性和破坏性操作均已审查。 - [ ] 任务代码与测试严格按 tasks/<version>/<migration-id>/ 规范组织并镜像测试目录,不平铺在 tasks 根目录下,不污染业务模块。 - [ ] 局部测试、类型检查、lint 和差异检查通过。
GitHub에서 보기