refactor: restructure database initialization and migration logic, moving to models package
This commit is contained in:
parent
bcc3aadb85
commit
a9c7598862
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/timetracker/backend/internal/config"
|
"github.com/timetracker/backend/internal/config"
|
||||||
"github.com/timetracker/backend/internal/db"
|
"github.com/timetracker/backend/internal/db"
|
||||||
|
"github.com/timetracker/backend/internal/models"
|
||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ func main() {
|
|||||||
|
|
||||||
// Run migrations
|
// Run migrations
|
||||||
fmt.Println("Running database migrations...")
|
fmt.Println("Running database migrations...")
|
||||||
if err = db.MigrateDB(); err != nil {
|
if err = models.MigrateDB(); err != nil {
|
||||||
log.Fatalf("Error migrating database: %v", err)
|
log.Fatalf("Error migrating database: %v", err)
|
||||||
}
|
}
|
||||||
fmt.Println("✓ Database migrations completed successfully")
|
fmt.Println("✓ Database migrations completed successfully")
|
||||||
|
@ -2,6 +2,7 @@ package db
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
@ -15,53 +16,30 @@ import (
|
|||||||
// Global variable for the DB connection
|
// Global variable for the DB connection
|
||||||
var db *gorm.DB
|
var db *gorm.DB
|
||||||
|
|
||||||
|
// ErrDBNotInitialized is returned when a database operation is attempted before initialization
|
||||||
|
var ErrDBNotInitialized = errors.New("database not initialized")
|
||||||
|
|
||||||
// InitDB initializes the database connection (once at startup)
|
// InitDB initializes the database connection (once at startup)
|
||||||
// with the provided configuration
|
// with the provided configuration
|
||||||
func InitDB(config config.DatabaseConfig) error {
|
func InitDB(config config.DatabaseConfig) error {
|
||||||
// Create DSN (Data Source Name)
|
// Create connection using the default database name
|
||||||
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
|
gormDB, err := createConnection(config, config.DBName)
|
||||||
config.Host, config.Port, config.User, config.Password, config.DBName, config.SSLMode)
|
|
||||||
|
|
||||||
// Configure GORM logger
|
|
||||||
gormLogger := logger.New(
|
|
||||||
log.New(log.Writer(), "\r\n", log.LstdFlags), // io writer
|
|
||||||
logger.Config{
|
|
||||||
SlowThreshold: 200 * time.Millisecond, // Slow SQL threshold
|
|
||||||
LogLevel: config.LogLevel, // Log level
|
|
||||||
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
|
|
||||||
Colorful: true, // Enable color
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// Establish database connection with custom logger
|
|
||||||
var err error
|
|
||||||
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
|
|
||||||
Logger: gormLogger,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error connecting to the database: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the global db instance
|
||||||
|
db = gormDB
|
||||||
|
|
||||||
// Configure connection pool
|
// Configure connection pool
|
||||||
sqlDB, err := db.DB()
|
return configureConnectionPool(db, config)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error getting database connection: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set connection pool parameters
|
// GetEngine returns the DB instance with context
|
||||||
sqlDB.SetMaxIdleConns(config.MaxIdleConns)
|
|
||||||
sqlDB.SetMaxOpenConns(config.MaxOpenConns)
|
|
||||||
sqlDB.SetConnMaxLifetime(config.MaxLifetime)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEngine returns the DB instance, possibly with context
|
|
||||||
func GetEngine(ctx context.Context) *gorm.DB {
|
func GetEngine(ctx context.Context) *gorm.DB {
|
||||||
if db == nil {
|
if db == nil {
|
||||||
panic("database not initialized")
|
panic(ErrDBNotInitialized)
|
||||||
}
|
}
|
||||||
// If a special transaction is in ctx, you could check it here
|
|
||||||
return db.WithContext(ctx)
|
return db.WithContext(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,3 +60,67 @@ func CloseDB() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetGormDB is used for special cases like database creation
|
||||||
|
func GetGormDB(dbConfig config.DatabaseConfig, dbName string) (*gorm.DB, error) {
|
||||||
|
return createConnection(dbConfig, dbName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateDB performs database migrations for all models
|
||||||
|
// This is a placeholder that will be called by models.MigrateDB
|
||||||
|
func MigrateDB() error {
|
||||||
|
if db == nil {
|
||||||
|
return ErrDBNotInitialized
|
||||||
|
}
|
||||||
|
// The actual migration is implemented in models.MigrateDB
|
||||||
|
// This is just a placeholder to make the migrate/main.go file work
|
||||||
|
return errors.New("MigrateDB should be called from models package")
|
||||||
|
}
|
||||||
|
|
||||||
|
// createConnection creates a new database connection with the given configuration
|
||||||
|
func createConnection(dbConfig config.DatabaseConfig, dbName string) (*gorm.DB, error) {
|
||||||
|
// Create DSN (Data Source Name)
|
||||||
|
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbName=%s sslmode=%s",
|
||||||
|
dbConfig.Host, dbConfig.Port, dbConfig.User, dbConfig.Password, dbName, dbConfig.SSLMode)
|
||||||
|
|
||||||
|
// Configure GORM logger
|
||||||
|
gormLogger := createGormLogger(dbConfig)
|
||||||
|
|
||||||
|
// Establish database connection with custom logger
|
||||||
|
gormDB, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||||
|
Logger: gormLogger,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error connecting to the database: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gormDB, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createGormLogger creates a configured GORM logger instance
|
||||||
|
func createGormLogger(dbConfig config.DatabaseConfig) logger.Interface {
|
||||||
|
return logger.New(
|
||||||
|
log.New(log.Writer(), "\r\n", log.LstdFlags), // io writer
|
||||||
|
logger.Config{
|
||||||
|
SlowThreshold: 200 * time.Millisecond, // Slow SQL threshold
|
||||||
|
LogLevel: dbConfig.LogLevel, // Log level
|
||||||
|
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
|
||||||
|
Colorful: true, // Enable color
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// configureConnectionPool sets up the connection pool parameters
|
||||||
|
func configureConnectionPool(db *gorm.DB, config config.DatabaseConfig) error {
|
||||||
|
sqlDB, err := db.DB()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting database connection: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set connection pool parameters
|
||||||
|
sqlDB.SetMaxIdleConns(config.MaxIdleConns)
|
||||||
|
sqlDB.SetMaxOpenConns(config.MaxOpenConns)
|
||||||
|
sqlDB.SetConnMaxLifetime(config.MaxLifetime)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
BIN
backend/migrate
Executable file
BIN
backend/migrate
Executable file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user