refactor: remove standalone migrate command, auto-migrate on startup

Migrations already run idempotently during RunServer startup via goose
(which tracks applied versions in goose_db_version). The separate
 command is redundant — removed it and consolidated
serveCmd/configFile/init into server.go.
This commit is contained in:
2026-07-27 14:43:22 +08:00
parent 90e53aa754
commit 264b84a738
4 changed files with 44 additions and 79 deletions
-69
View File
@@ -1,69 +0,0 @@
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/peterqiu0516/sub-store/internal/config"
"github.com/peterqiu0516/sub-store/internal/database"
)
//go:generate echo "embed handled in migrate.go"
var migrateCmd = &cobra.Command{
Use: "migrate",
Short: "Run database migrations",
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.Load(configFile)
if err != nil {
return err
}
db, err := database.InitDB(cfg.Database.Path)
if err != nil {
return err
}
defer db.Close()
return database.RunMigrations(db)
},
}
var configFile string
func init() {
rootCmd.AddCommand(migrateCmd)
migrateCmd.Flags().StringVarP(&configFile, "config", "c", "", "config file path")
serveCmd.Flags().StringVarP(&configFile, "config", "c", "", "config file path")
rootCmd.AddCommand(serveCmd)
}
var serveCmd = &cobra.Command{
Use: "serve",
Short: "Start the Sub-Store HTTP server",
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.Load(configFile)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
return RunServer(cfg)
},
}
func RunServer(cfg *config.Config) error {
db, err := database.InitDB(cfg.Database.Path)
if err != nil {
return err
}
defer db.Close()
if err := database.RunMigrations(db); err != nil {
return err
}
return startFiber(cfg, db)
}
// startFiber is implemented in server.go (same package).
+38
View File
@@ -11,6 +11,7 @@ import (
"github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/spf13/cobra"
"github.com/peterqiu0516/sub-store/internal/config" "github.com/peterqiu0516/sub-store/internal/config"
"github.com/peterqiu0516/sub-store/internal/database" "github.com/peterqiu0516/sub-store/internal/database"
@@ -18,6 +19,43 @@ import (
"github.com/peterqiu0516/sub-store/internal/middleware" "github.com/peterqiu0516/sub-store/internal/middleware"
) )
var configFile string
var serveCmd = &cobra.Command{
Use: "serve",
Short: "Start the Sub-Store HTTP server",
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.Load(configFile)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
return RunServer(cfg)
},
}
func init() {
rootCmd.AddCommand(serveCmd)
serveCmd.Flags().StringVarP(&configFile, "config", "c", "", "config file path")
}
// RunServer opens the database, applies migrations (idempotent — goose tracks
// applied versions in goose_db_version), then starts the HTTP server.
func RunServer(cfg *config.Config) error {
db, err := database.InitDB(cfg.Database.Path)
if err != nil {
return err
}
defer db.Close()
// Auto-migrate on every startup; goose is idempotent so this is safe to call repeatedly.
if err := database.RunMigrations(db); err != nil {
return err
}
return startFiber(cfg, db)
}
func startFiber(cfg *config.Config, db *sqlx.DB) error { func startFiber(cfg *config.Config, db *sqlx.DB) error {
logrus.SetFormatter(&logrus.TextFormatter{ logrus.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true, FullTimestamp: true,
+4 -8
View File
@@ -62,8 +62,7 @@ sub-store/
├── main.go # 入口,调用 cmd ├── main.go # 入口,调用 cmd
├── cmd/ ├── cmd/
│ ├── root.go # cobra root command │ ├── root.go # cobra root command
│ ├── serve.go # sub-store serve (启动 HTTP 服务) │ ├── serve.go # sub-store serve (启动 HTTP 服务,启动时自动 migrate)
│ ├── migrate.go # sub-store migrate (执行数据库迁移)
│ └── version.go # sub-store version │ └── version.go # sub-store version
├── internal/ ├── internal/
│ ├── config/ │ ├── config/
@@ -322,11 +321,11 @@ ON source_cache(cached_at + ttl);
| 任务 | 产出 | 依赖库 | | 任务 | 产出 | 依赖库 |
|------|------|--------| |------|------|--------|
| go mod init + 依赖引入 | `go.mod` | 全部 | | go mod init + 依赖引入 | `go.mod` | 全部 |
| cobra root/serve/migrate/version 命令 | `cmd/*.go` | cobra | | cobra root/serve/version 命令 | `cmd/*.go` | cobra |
| viper 配置加载 | `internal/config/config.go` | viper | | viper 配置加载 | `internal/config/config.go` | viper |
| logrus 日志初始化 | 日志格式化、级别、输出 | logrus | | logrus 日志初始化 | 日志格式化、级别、输出 | logrus |
| SQLite 连接初始化 | `internal/database/db.go` | modernc/sqlite, sqlx | | SQLite 连接初始化 | `internal/database/db.go` | modernc/sqlite, sqlx |
| goose 迁移执行 | `cmd/migrate.go` | goose | | goose 迁移执行(启动时自动) | `internal/database/migrations.go` | goose |
| 3 个 migration SQL 文件 | `internal/database/migrations/` | | | 3 个 migration SQL 文件 | `internal/database/migrations/` | |
| Fiber app 骨架 | 路由注册、健康检查 | fiber/v3 | | Fiber app 骨架 | 路由注册、健康检查 | fiber/v3 |
| 优雅关闭 | signal handling | | | 优雅关闭 | signal handling | |
@@ -830,11 +829,8 @@ output: YAML with proxies: [{name:"test", type:"ss", ...}]
# 构建 # 构建
go build -o sub-store ./main.go go build -o sub-store ./main.go
# 运行 # 运行(启动时自动执行迁移,幂等)
./sub-store serve --config config.yaml ./sub-store serve --config config.yaml
# 迁移
./sub-store migrate --config config.yaml
``` ```
### 9.2 配置 ### 9.2 配置
+2 -2
View File
@@ -42,7 +42,7 @@
| 30 | importStorage 导入顺序 | settings→sources→templates→collections | `handler/storage.go` | | 30 | importStorage 导入顺序 | settings→sources→templates→collections | `handler/storage.go` |
| 31 | exportStorage 排除内置模板 | 过滤 BuiltinTemplateIDs | `handler/storage.go` | | 31 | exportStorage 排除内置模板 | 过滤 BuiltinTemplateIDs | `handler/storage.go` |
| 32 | source_cache TTL 清理 | 后台 goroutine 定时清理 | `database/cache_repo.go` | | 32 | source_cache TTL 清理 | 后台 goroutine 定时清理 | `database/cache_repo.go` |
| 33 | goose 迁移嵌入 | //go:embed + SetBaseFS | `cmd/migrate.go` | | 33 | goose 迁移嵌入 | //go:embed + SetBaseFS | `database/migrations.go` |
| 34 | goroutine 关闭安全 | sync.WaitGroup + context | `service/subscription.go` | | 34 | goroutine 关闭安全 | sync.WaitGroup + context | `service/subscription.go` |
| 35 | 缓存操作错误吞咽 | recover + 日志,不传播 | `database/cache_repo.go` | | 35 | 缓存操作错误吞咽 | recover + 日志,不传播 | `database/cache_repo.go` |
| 36 | 并发 wait 延迟 | 保留 waitMs 参数 | `service/concurrency.go` | | 36 | 并发 wait 延迟 | 保留 waitMs 参数 | `service/concurrency.go` |
@@ -491,7 +491,7 @@ func RunMigrations(db *sqlx.DB) error {
} }
``` ```
**落地**`cmd/migrate.go` + `database/migrations/*.sql`。 **落地**`database/migrations.go` + `database/migrations/*.sql`。启动时自动执行,幂等(goose 跟踪 `goose_db_version`)。
--- ---