- Updated main.go to initialize email service and include it in the dependency injection container. - Refactored handlers to utilize context in service method calls, improving consistency and error handling. - Introduced new service options for upload, security, and captcha services, enhancing modularity and testability. - Removed unused repository implementations to streamline the codebase. This commit continues the effort to improve the architecture by ensuring all services are properly injected and utilized across the application.
116 lines
2.4 KiB
Go
116 lines
2.4 KiB
Go
package database
|
||
|
||
import (
|
||
"carrotskin/internal/model"
|
||
"carrotskin/pkg/config"
|
||
"fmt"
|
||
"sync"
|
||
|
||
"go.uber.org/zap"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
var (
|
||
// dbInstance 全局数据库实例
|
||
dbInstance *gorm.DB
|
||
// once 确保只初始化一次
|
||
once sync.Once
|
||
// initError 初始化错误
|
||
initError error
|
||
)
|
||
|
||
// Init 初始化数据库连接(线程安全,只会执行一次)
|
||
func Init(cfg config.DatabaseConfig, logger *zap.Logger) error {
|
||
once.Do(func() {
|
||
dbInstance, initError = New(cfg)
|
||
if initError != nil {
|
||
logger.Error("数据库初始化失败", zap.Error(initError))
|
||
return
|
||
}
|
||
logger.Info("数据库连接成功")
|
||
})
|
||
return initError
|
||
}
|
||
|
||
// GetDB 获取数据库实例(线程安全)
|
||
func GetDB() (*gorm.DB, error) {
|
||
if dbInstance == nil {
|
||
return nil, fmt.Errorf("数据库未初始化,请先调用 database.Init()")
|
||
}
|
||
return dbInstance, nil
|
||
}
|
||
|
||
// MustGetDB 获取数据库实例,如果未初始化则panic
|
||
func MustGetDB() *gorm.DB {
|
||
db, err := GetDB()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return db
|
||
}
|
||
|
||
// AutoMigrate 自动迁移数据库表结构
|
||
func AutoMigrate(logger *zap.Logger) error {
|
||
db, err := GetDB()
|
||
if err != nil {
|
||
return fmt.Errorf("获取数据库实例失败: %w", err)
|
||
}
|
||
|
||
logger.Info("开始执行数据库迁移...")
|
||
|
||
// 迁移所有表 - 注意顺序:先创建被引用的表,再创建引用表
|
||
// 使用分批迁移,避免某些表的问题影响其他表
|
||
tables := []interface{}{
|
||
// 用户相关表(先创建,因为其他表可能引用它)
|
||
&model.User{},
|
||
&model.UserPointLog{},
|
||
&model.UserLoginLog{},
|
||
|
||
// 档案相关表
|
||
&model.Profile{},
|
||
|
||
// 材质相关表
|
||
&model.Texture{},
|
||
&model.UserTextureFavorite{},
|
||
&model.TextureDownloadLog{},
|
||
|
||
// 认证相关表
|
||
&model.Token{},
|
||
|
||
// Yggdrasil相关表(在User之后创建,因为它引用User)
|
||
&model.Yggdrasil{},
|
||
|
||
// 系统配置表
|
||
&model.SystemConfig{},
|
||
|
||
// 审计日志表
|
||
&model.AuditLog{},
|
||
|
||
// Casbin权限规则表
|
||
&model.CasbinRule{},
|
||
}
|
||
|
||
// 批量迁移表
|
||
if err := db.AutoMigrate(tables...); err != nil {
|
||
logger.Error("数据库迁移失败", zap.Error(err))
|
||
return fmt.Errorf("数据库迁移失败: %w", err)
|
||
}
|
||
|
||
logger.Info("数据库迁移完成")
|
||
return nil
|
||
}
|
||
|
||
// Close 关闭数据库连接
|
||
func Close() error {
|
||
if dbInstance == nil {
|
||
return nil
|
||
}
|
||
|
||
sqlDB, err := dbInstance.DB()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return sqlDB.Close()
|
||
}
|