1
0

fix: 修复合并后代码质量问题

- 修正 Makefile 迁移目录路径(sqlite3 → sqlite)
- 统一 database.go 日志风格(log.Printf → zapLogger)
- 修复 config.go validator 标签大小写
- 修复 database_test.go 测试使用 nil logger
- 移除未使用的 log 导入
This commit is contained in:
2026-04-23 16:58:01 +08:00
parent 53e477d383
commit 8c075194e5
6 changed files with 50 additions and 27 deletions

View File

@@ -68,15 +68,15 @@ backend-generate:
backend-db-up:
@echo "Running database migration up..."
cd backend && goose -dir migrations/sqlite3 sqlite3 "$(DB_PATH)" up
cd backend && goose -dir migrations/sqlite sqlite3 "$(DB_PATH)" up
backend-db-down:
@echo "Running database migration down..."
cd backend && goose -dir migrations/sqlite3 sqlite3 "$(DB_PATH)" down
cd backend && goose -dir migrations/sqlite sqlite3 "$(DB_PATH)" down
backend-db-status:
@echo "Checking database migration status..."
cd backend && goose -dir migrations/sqlite3 sqlite3 "$(DB_PATH)" status
cd backend && goose -dir migrations/sqlite sqlite3 "$(DB_PATH)" status
backend-db-create:
@read -p "Migration name: " name; \

View File

@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"io/fs"
"log"
"net"
"net/http"
"os"

View File

@@ -33,12 +33,12 @@ type ServerConfig struct {
// DatabaseConfig 数据库配置
type DatabaseConfig struct {
Driver string `yaml:"driver" mapstructure:"driver" validate:"required,oneof=sqlite mysql"`
Path string `yaml:"path" mapstructure:"path" validate:"required_if=Driver sqlite"`
Host string `yaml:"host" mapstructure:"host" validate:"required_if=Driver mysql"`
Port int `yaml:"port" mapstructure:"port" validate:"required_if=Driver mysql,min=1,max=65535"`
User string `yaml:"user" mapstructure:"user" validate:"required_if=Driver mysql"`
Path string `yaml:"path" mapstructure:"path" validate:"required_if=driver sqlite"`
Host string `yaml:"host" mapstructure:"host" validate:"required_if=driver mysql"`
Port int `yaml:"port" mapstructure:"port" validate:"required_if=driver mysql,min=1,max=65535"`
User string `yaml:"user" mapstructure:"user" validate:"required_if=driver mysql"`
Password string `yaml:"password" mapstructure:"password"`
DBName string `yaml:"dbname" mapstructure:"dbname" validate:"required_if=Driver mysql"`
DBName string `yaml:"dbname" mapstructure:"dbname" validate:"required_if=driver mysql"`
MaxIdleConns int `yaml:"max_idle_conns" mapstructure:"max_idle_conns" validate:"required,min=1"`
MaxOpenConns int `yaml:"max_open_conns" mapstructure:"max_open_conns" validate:"required,min=1"`
ConnMaxLifetime time.Duration `yaml:"conn_max_lifetime" mapstructure:"conn_max_lifetime" validate:"required"`

View File

@@ -2,7 +2,6 @@ package database
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
@@ -18,16 +17,16 @@ import (
)
func Init(cfg *config.DatabaseConfig, zapLogger *zap.Logger) (*gorm.DB, error) {
db, err := initDB(cfg)
db, err := initDB(cfg, zapLogger)
if err != nil {
return nil, fmt.Errorf("初始化数据库失败: %w", err)
}
if err := runMigrations(db, cfg.Driver); err != nil {
if err := runMigrations(db, cfg.Driver, zapLogger); err != nil {
return nil, fmt.Errorf("数据库迁移失败: %w", err)
}
configurePool(db, cfg)
configurePool(db, cfg, zapLogger)
return db, nil
}
@@ -40,7 +39,7 @@ func Close(db *gorm.DB) {
sqlDB.Close()
}
func initDB(cfg *config.DatabaseConfig) (*gorm.DB, error) {
func initDB(cfg *config.DatabaseConfig, zapLogger *zap.Logger) (*gorm.DB, error) {
gormConfig := &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
}
@@ -49,27 +48,31 @@ func initDB(cfg *config.DatabaseConfig) (*gorm.DB, error) {
case "mysql":
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=true&loc=Local",
cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DBName)
if zapLogger != nil {
zapLogger.Info("连接 MySQL 数据库",
zap.String("host", cfg.Host),
zap.Int("port", cfg.Port),
zap.String("database", cfg.DBName))
}
return gorm.Open(mysql.Open(dsn), gormConfig)
default:
dbDir := filepath.Dir(cfg.Path)
if err := os.MkdirAll(dbDir, 0755); err != nil {
return nil, fmt.Errorf("创建数据库目录失败: %w", err)
}
if zapLogger != nil {
zapLogger.Info("连接 SQLite 数据库", zap.String("path", cfg.Path))
}
return gorm.Open(sqlite.Open(cfg.Path), gormConfig)
}
}
func runMigrations(db *gorm.DB, driver string) error {
func runMigrations(db *gorm.DB, driver string, zapLogger *zap.Logger) error {
sqlDB, err := db.DB()
if err != nil {
return err
}
migrationsDir := getMigrationsDir(driver)
if _, err := os.Stat(migrationsDir); os.IsNotExist(err) {
return fmt.Errorf("迁移目录不存在: %s", migrationsDir)
}
gooseDialect := "sqlite3"
migrationsSubDir := "sqlite"
if driver == "mysql" {
@@ -77,19 +80,31 @@ func runMigrations(db *gorm.DB, driver string) error {
migrationsSubDir = "mysql"
}
migrationsDir := getMigrationsDir(driver)
if _, err := os.Stat(migrationsDir); os.IsNotExist(err) {
return fmt.Errorf("迁移目录不存在: %s", migrationsDir)
}
if zapLogger != nil {
zapLogger.Info("执行数据库迁移",
zap.String("dialect", gooseDialect),
zap.String("dir", migrationsSubDir))
}
goose.SetDialect(gooseDialect)
if err := goose.Up(sqlDB, migrationsDir); err != nil {
return err
}
log.Printf("使用 %s 方言执行迁移,目录: %s", gooseDialect, migrationsSubDir)
return nil
}
func configurePool(db *gorm.DB, cfg *config.DatabaseConfig) {
func configurePool(db *gorm.DB, cfg *config.DatabaseConfig, zapLogger *zap.Logger) {
if cfg.Driver == "sqlite" {
if err := db.Exec("PRAGMA journal_mode=WAL").Error; err != nil {
log.Printf("警告: 启用 WAL 模式失败: %v", err)
if zapLogger != nil {
zapLogger.Warn("启用 WAL 模式失败", zap.Error(err))
}
}
}
@@ -101,8 +116,12 @@ func configurePool(db *gorm.DB, cfg *config.DatabaseConfig) {
sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)
sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime)
log.Printf("数据库连接池配置: MaxIdle=%d, MaxOpen=%d, MaxLifetime=%v",
cfg.MaxIdleConns, cfg.MaxOpenConns, cfg.ConnMaxLifetime)
if zapLogger != nil {
zapLogger.Info("数据库连接池配置",
zap.Int("max_idle_conns", cfg.MaxIdleConns),
zap.Int("max_open_conns", cfg.MaxOpenConns),
zap.Duration("conn_max_lifetime", cfg.ConnMaxLifetime))
}
}
func getMigrationsDir(driver string) string {

View File

@@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"nex/backend/internal/config"
)
@@ -20,7 +21,8 @@ func TestInit_SQLite(t *testing.T) {
ConnMaxLifetime: 0,
}
db, err := Init(cfg, nil)
zapLogger := zap.NewNop()
db, err := Init(cfg, zapLogger)
require.NoError(t, err)
require.NotNil(t, db)
defer Close(db)
@@ -40,7 +42,8 @@ func TestClose(t *testing.T) {
ConnMaxLifetime: 0,
}
db, err := Init(cfg, nil)
zapLogger := zap.NewNop()
db, err := Init(cfg, zapLogger)
require.NoError(t, err)
require.NotNil(t, db)

View File

@@ -4,6 +4,7 @@ cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQ
cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng=
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
github.com/ClickHouse/ch-go v0.71.0/go.mod h1:NwbNc+7jaqfY58dmdDUbG4Jl22vThgx1cYjBw0vtgXw=
github.com/ClickHouse/clickhouse-go/v2 v2.43.0/go.mod h1:o6jf7JM/zveWC/PP277BLxjHy5KjnGX/jfljhM4s34g=
@@ -25,6 +26,7 @@ github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6v
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=