You've already forked agentic-coding-workflow
46 lines
1.4 KiB
Go
46 lines
1.4 KiB
Go
// Package db 提供数据库相关的基础设施工具,包括 golang-migrate 迁移运行器。
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/golang-migrate/migrate/v4"
|
|
// 注册 postgres 数据库驱动(database://postgres)。
|
|
_ "github.com/golang-migrate/migrate/v4/database/postgres"
|
|
// 注册 file:// 迁移源驱动。
|
|
_ "github.com/golang-migrate/migrate/v4/source/file"
|
|
)
|
|
|
|
// Migrate 跑指定路径下的迁移到最新版本。ctx 取消可让本函数提前返回 ctx.Err(),
|
|
// 但底层 golang-migrate 不接 ctx,已经 in-flight 的 Up() 会继续在后台 goroutine
|
|
// 中执行直到自然完成(或外部 statement_timeout 触发)。
|
|
// migrationsPath 形如 "file://migrations",dsn 为 postgres 连接串。
|
|
// 当无新迁移可应用时(migrate.ErrNoChange)视为成功,返回 nil。
|
|
func Migrate(ctx context.Context, dsn, migrationsPath string) error {
|
|
m, err := migrate.New(migrationsPath, dsn)
|
|
if err != nil {
|
|
return fmt.Errorf("init migrate: %w", err)
|
|
}
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
if err := m.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
|
|
errCh <- err
|
|
return
|
|
}
|
|
errCh <- nil
|
|
}()
|
|
select {
|
|
case err := <-errCh:
|
|
_, _ = m.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("migrate up: %w", err)
|
|
}
|
|
return nil
|
|
case <-ctx.Done():
|
|
// 注意:m.Close 不能在这里调,会与正在跑的 Up() 竞态。让 goroutine 自然结束。
|
|
return ctx.Err()
|
|
}
|
|
}
|