Help us shape the future of Go! Take the 2026 Go Developer Survey

engine

package
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2026 License: AGPL-3.0 Imports: 5 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Registry []Migration

Registry 聚合所有已注册迁移,注册顺序 = 执行顺序。 具体迁移包(如 internal/migrate/v160)在 init() 里调用 Register 自注册; migrate.Run 遍历本注册表执行,对具体迁移无感知。

Functions

func MarkStepsDone

func MarkStepsDone(db *gorm.DB, log *slog.Logger, migration string, steps []Step) error

MarkStepsDone 原子登记无需执行的数据迁移。它与 markStep 的“状态写入失败仅告警” 语义不同:新库/最终 schema 必须一次性得到全部 done 或完全不写入,避免进程中断 后留下半组状态并在下次被误当作待恢复的旧库迁移。

func Register

func Register(m Migration)

Register 注册一次迁移,供具体迁移包的 init() 调用。

func RunSteps

func RunSteps(db *gorm.DB, log *slog.Logger, migration string, steps []Step) error

RunSteps 按注册表顺序驱动一次迁移的步骤(框架统一写状态)。

幂等 / 中断恢复:

  • 已 done 的 step 跳过;未 done 的置 running → 执行 → done / failed
  • 某 step 写 done 前中断 → 该 step 未 done → 下次启动从它重跑(step 内部幂等)

状态记录失败只 warn 不阻塞(下次启动重跑该 step,幂等无害)。

Types

type MigrateState

type MigrateState struct {
	ID         int64      `gorm:"column:id;primaryKey;autoIncrement"                      json:"id"`
	Migration  string     `gorm:"column:migration;not null;uniqueIndex:uk_migration_step" json:"migration"`   // 迁移标识,如 "v1.6.0-chapter-id-refactor"
	Step       string     `gorm:"column:step;not null;uniqueIndex:uk_migration_step"      json:"step"`        // 迁移内 step 标识(语义化 key,如 "1-crossref-data")
	Status     string     `gorm:"column:status;not null;index"                            json:"status"`      // "running" | "done" | "failed"(未开始无行)
	StartedAt  *time.Time `gorm:"column:started_at"                                       json:"started_at"`  // 本 step 开始时间,nullable
	FinishedAt *time.Time `gorm:"column:finished_at"                                      json:"finished_at"` // 本 step 完成时间,nullable
	Error      string     `gorm:"column:error"                                            json:"error"`       // failed 时的错误信息
	CreatedAt  time.Time  `gorm:"column:created_at;autoCreateTime"                        json:"created_at"`
	UpdatedAt  time.Time  `gorm:"column:updated_at;autoUpdateTime"                        json:"updated_at"`
}

MigrateState 是迁移进度跟踪表,按"迁移 + step"两级记录。

设计原则:

  • 一行 = (migration, step)。migration 标识一次大迁移(如 "v1.6.0-chapter-id-refactor"), step 标识该迁移内的执行步骤(语义化 key,如 "1-crossref-data")
  • status 取值:running | done | failed(未开始 = 无行,stepStatus 返回空串)
  • 幂等:迁移启动时查 migration 组内非 done 的 step,逐个执行;每步"内部执行完再写 done"
  • 中断续跑:某 step 写 done 前中断 → 该 step 未 done → 下次从它重跑(step 内部幂等)
  • 备份/完成判断:查 migration 组的行是否全部 done,只看本组,不看其他迁移
  • 新用户 DB 初始化后所有 step INSERT 为 done(无需迁移)

时间戳语义:

  • started_at:本 step 开始执行时间(nullable,未执行时为 NULL)
  • finished_at:本 step 执行完成时间(nullable,running 时为 NULL)
  • error:failed 时填写错误信息,便于诊断中断原因

func (MigrateState) TableName

func (MigrateState) TableName() string

TableName 指定 GORM 表名。

type Migration

type Migration struct {
	Name        string // 迁移标识,如 "v1.6.0-chapter-id-refactor",写入 migrate_state.migration
	Description string // 迁移目的简述(本次迁移为了什么、主要做什么),打印进日志便于排查
	Destructive bool   // 是否破坏性迁移(删列/rename/数据重写等):true 时 migrate.Run 会在执行前自动备份全量数据

	// NeedsMigration 仅在既有数据库缺少本 migration 的 migrate_state 时调用,识别
	// 是否仍处于该 migration 的旧 schema。应返回 error 拒绝无法安全识别的混合 schema。
	NeedsMigration  func(db *gorm.DB) (bool, error)
	PreSchemaSteps  []Step // 当前 model AutoMigrate 前执行,例如历史字段改名
	PostSchemaSteps []Step // 当前 model AutoMigrate 后执行,例如数据重写、文件迁移、删旧列
}

Migration 描述一次迁移。PreSchemaSteps 必须在当前 model 的 AutoMigrate 前运行; PostSchemaSteps 则在其后运行。两类步骤均按 Registry 注册顺序执行。

func (Migration) AllSteps

func (m Migration) AllSteps() []Step

AllSteps 按迁移的完整执行顺序返回所有步骤。

type Plan

type Plan struct {
	Migration Migration
	Action    PlanAction
}

Plan 是根据启动前 schema 和 migrate_state 得出的单次迁移计划。

func BuildPlans

func BuildPlans(db *gorm.DB, log *slog.Logger, isNewDatabase bool, registry []Migration) ([]Plan, error)

BuildPlans 在任何业务 model AutoMigrate 前为全部注册迁移生成计划。 对于已有状态的迁移,migrate_state 是唯一真相;只有完全没有状态记录的既有库才 使用 Migration.NeedsMigration 识别历史 schema。

type PlanAction

type PlanAction uint8

PlanAction 是一次启动中对一个 migration 的执行计划。

const (
	PlanSkip     PlanAction = iota // 所有已知步骤均 done
	PlanRun                        // 运行步骤,或从未完成状态恢复
	PlanMarkDone                   // 当前 schema 无需迁移,仅登记步骤完成
)

type Step

type Step interface {
	Key() string                             // 步骤标识(迁移内序数 N-描述,如 "1-crossref-data")
	Run(db *gorm.DB, log *slog.Logger) error // 业务逻辑,幂等可重入
}

Step 描述一个迁移步骤:由 RunSteps 统一驱动。

契约:Run 内部必须幂等可重入——自身完成条件(HasColumn / IS NULL / 目标文件存在等) 已满足时直接返回 nil。中断后框架从"未 done"的 step 重跑,靠此契约保证安全。

设计:Step 是接口而非结构体。具体迁移包(如 internal/migrate/v160)用自己的私有 step 类型实现它并注册进 Registry,migrate 包无需感知具体迁移。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL