package database import ( "fmt" "time" "github.com/yyhuni/lunafox/server/internal/config" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/schema" ) // DB is the global database instance var DB *gorm.DB // NewDatabase creates a new database connection func NewDatabase(cfg *config.DatabaseConfig) (*gorm.DB, error) { dsn := cfg.DSN() db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ NamingStrategy: schema.NamingStrategy{ SingularTable: true, // Use singular table names (e.g., "target" not "targets") }, }) if err != nil { return nil, fmt.Errorf("failed to connect to database: %w", err) } // Get underlying sql.DB to configure connection pool sqlDB, err := db.DB() if err != nil { return nil, fmt.Errorf("failed to get underlying sql.DB: %w", err) } // Configure connection pool sqlDB.SetMaxOpenConns(cfg.MaxOpenConns) sqlDB.SetMaxIdleConns(cfg.MaxIdleConns) sqlDB.SetConnMaxLifetime(time.Duration(cfg.ConnMaxLifetime) * time.Second) // Verify connection if err := sqlDB.Ping(); err != nil { return nil, fmt.Errorf("failed to ping database: %w", err) } return db, nil } // InitDatabase initializes the global database instance func InitDatabase(cfg *config.DatabaseConfig) error { var err error DB, err = NewDatabase(cfg) return err } // Close closes the database connection func Close() error { if DB != nil { sqlDB, err := DB.DB() if err != nil { return err } return sqlDB.Close() } return nil } // Ping checks if the database connection is alive func Ping() error { if DB == nil { return fmt.Errorf("database not initialized") } sqlDB, err := DB.DB() if err != nil { return err } return sqlDB.Ping() } // GetDB returns the global database instance func GetDB() *gorm.DB { return DB }