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:
@@ -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).
|
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 配置
|
||||||
|
|||||||
@@ -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`)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user