package db import ( "context" "fmt" "log" "time" "github.com/timetracker/backend/internal/config" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" ) // Global variable for the DB connection var db *gorm.DB // InitDB initializes the database connection (once at startup) // with the provided configuration func InitDB(config config.DatabaseConfig) error { // Create DSN (Data Source Name) dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", 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 { return fmt.Errorf("error connecting to the database: %w", err) } // Configure connection pool 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 } // GetEngine returns the DB instance, possibly with context func GetEngine(ctx context.Context) *gorm.DB { if db == nil { panic("database not initialized") } // If a special transaction is in ctx, you could check it here return db.WithContext(ctx) } // CloseDB closes the database connection func CloseDB() error { if db == nil { return nil } sqlDB, err := db.DB() if err != nil { return fmt.Errorf("error getting database connection: %w", err) } if err := sqlDB.Close(); err != nil { return fmt.Errorf("error closing database connection: %w", err) } return nil }