initial commit
This commit is contained in:
99
internal/pkg/database/database.go
Normal file
99
internal/pkg/database/database.go
Normal file
@@ -0,0 +1,99 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user