Files
base/internal/pkg/database/database.go
2026-04-10 18:25:21 +03:30

100 lines
2.8 KiB
Go

package database
import (
"database/sql"
"fmt"
"time"
"github.com/rs/zerolog"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"base/config"
"base/pkg/metrics"
)
// NewRWDatabaseConnection creates a new database connection
func NewRWDatabaseConnection(cfg *config.AppConfig, logger zerolog.Logger, metric *metrics.Metrics) (*gorm.DB, error) {
start := time.Now()
lg := logger.
With().
Str("module", "database").
Int("maxOpenConnection", cfg.Database.MaxOpenConns).
Int("maxIdleConnection", cfg.Database.MaxIdleConns).
Logger()
gormConfig := &gorm.Config{Logger: NewGormLogger(logger, time.Second*5)}
wrDB, sqlDB, err := wr(cfg, gormConfig)
if err != nil {
fmt.Println("[DATABASE CONNECTION ERROR]Failed to connect to database", err.Error())
metric.RecordDatabaseQuery("ConnectWR", "database", time.Since(start), err)
lg.Error().
Err(err).
Msg("failed to connect to database")
return nil, err
}
metric.RecordDatabaseQuery("ConnectWR", "database", time.Since(start), nil)
// Start monitoring connection pool metrics
go monitorConnectionPool(sqlDB, metric, logger)
duration := time.Since(start)
metric.RecordDatabaseQuery("Connect", "database", duration, nil)
lg.Info().Msg("Database connection established")
return wrDB, nil
}
func wr(config *config.AppConfig, gormConfig *gorm.Config) (*gorm.DB, *sql.DB, error) {
// PostgreSQL DSN format: postgres://user:password@host:port/dbname?sslmode=disable
dsn := fmt.Sprintf(
"host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=UTC",
config.PgDatabaseConfig.Host,
config.PgDatabaseConfig.User,
config.PgDatabaseConfig.Password,
config.PgDatabaseConfig.Name,
config.PgDatabaseConfig.Port,
config.PgDatabaseConfig.SSLMode,
)
db, err := gorm.Open(postgres.Open(dsn), gormConfig)
if err != nil {
return nil, nil, err
}
// Get the underlying sql.DB
sqlDB, err := db.DB()
if err != nil {
return nil, nil, err
}
sqlDB.SetMaxIdleConns(int(config.PgDatabaseConfig.PoolConfig.MinConn))
sqlDB.SetMaxOpenConns(int(config.PgDatabaseConfig.PoolConfig.MaxConn))
// Parse and set connection timeouts from config
// TODO: this is not type safe
if config.PgDatabaseConfig.PoolConfig.MaxConnIdleTime.String() != "" {
if idleTime, parseDurationErr := time.ParseDuration(config.PgDatabaseConfig.PoolConfig.MaxConnIdleTime.String()); parseDurationErr == nil {
sqlDB.SetConnMaxIdleTime(idleTime)
} else {
sqlDB.SetConnMaxIdleTime(5 * time.Minute)
}
}
if config.PgDatabaseConfig.PoolConfig.MaxConnLifetime.String() != "" {
if lifetime, parseDurationErr := time.ParseDuration(config.PgDatabaseConfig.PoolConfig.MaxConnLifetime.String()); parseDurationErr == nil {
sqlDB.SetConnMaxLifetime(lifetime)
} else {
sqlDB.SetConnMaxLifetime(30 * time.Minute)
}
}
return db, sqlDB, nil
}