15357fd3c0
yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarbacreate and moove into new directories for BegushiyBashkir and yalarba
139 lines
3.6 KiB
Go
139 lines
3.6 KiB
Go
package database
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"go.uber.org/zap"
|
|
"gorm.io/driver/postgres"
|
|
"gorm.io/gorm"
|
|
|
|
"api_bb/pkg/logger"
|
|
)
|
|
|
|
type Database struct {
|
|
DB *gorm.DB
|
|
cfg *Config
|
|
}
|
|
|
|
type Config struct {
|
|
URL string
|
|
}
|
|
|
|
func NewDatabase(cfg *Config) *Database {
|
|
return &Database{
|
|
cfg: cfg,
|
|
}
|
|
}
|
|
|
|
// Connect устанавливает соединение с базой данных
|
|
func (d *Database) Connect() error {
|
|
zapLogger := logger.Get()
|
|
|
|
// Логирование попытки подключения к БД
|
|
zapLogger.Info("attempting to connect to database",
|
|
zap.String("host", ExtractHostFromDSN(d.cfg.URL)),
|
|
zap.String("database", ExtractDBNameFromDSN(d.cfg.URL)),
|
|
)
|
|
|
|
db, err := gorm.Open(postgres.Open(d.cfg.URL), &gorm.Config{})
|
|
if err != nil {
|
|
zapLogger.Error("failed to connect to database",
|
|
zap.Error(err),
|
|
zap.String("database_url", MaskPassword(d.cfg.URL)),
|
|
)
|
|
return fmt.Errorf("failed to connect to database: %w", err)
|
|
}
|
|
|
|
d.DB = db
|
|
|
|
// Логирование успешного подключения к БД
|
|
zapLogger.Info("successfully connected to database",
|
|
zap.String("host", ExtractHostFromDSN(d.cfg.URL)),
|
|
zap.String("database", ExtractDBNameFromDSN(d.cfg.URL)),
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Ping проверяет соединение с базой данных
|
|
func (d *Database) Ping() error {
|
|
zapLogger := logger.Get()
|
|
|
|
sqlDB, err := d.DB.DB()
|
|
if err != nil {
|
|
zapLogger.Error("failed to get database instance", zap.Error(err))
|
|
return fmt.Errorf("failed to get database instance: %w", err)
|
|
}
|
|
|
|
if err := sqlDB.Ping(); err != nil {
|
|
zapLogger.Error("database ping failed", zap.Error(err))
|
|
return fmt.Errorf("database ping failed: %w", err)
|
|
}
|
|
|
|
zapLogger.Info("database ping successful")
|
|
return nil
|
|
}
|
|
|
|
// Close закрывает соединение с базой данных
|
|
func (d *Database) Close() error {
|
|
zapLogger := logger.Get()
|
|
|
|
if d.DB == nil {
|
|
return nil
|
|
}
|
|
|
|
sqlDB, err := d.DB.DB()
|
|
if err != nil {
|
|
zapLogger.Error("failed to get database instance for closing", zap.Error(err))
|
|
return fmt.Errorf("failed to get database instance: %w", err)
|
|
}
|
|
|
|
zapLogger.Info("closing database connection")
|
|
if err := sqlDB.Close(); err != nil {
|
|
zapLogger.Error("failed to close database connection", zap.Error(err))
|
|
return fmt.Errorf("failed to close database connection: %w", err)
|
|
}
|
|
|
|
zapLogger.Info("database connection closed successfully")
|
|
return nil
|
|
}
|
|
|
|
// Вспомогательные функции для работы с DSN
|
|
|
|
// ExtractHostFromDSN извлекает хост из DSN строки
|
|
func ExtractHostFromDSN(dsn string) string {
|
|
// Простая реализация для PostgreSQL DSN
|
|
parts := strings.Split(dsn, " ")
|
|
for _, part := range parts {
|
|
if strings.HasPrefix(part, "host=") {
|
|
return strings.TrimPrefix(part, "host=")
|
|
}
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
// ExtractDBNameFromDSN извлекает имя базы данных из DSN строки
|
|
func ExtractDBNameFromDSN(dsn string) string {
|
|
// Простая реализация для PostgreSQL DSN
|
|
parts := strings.Split(dsn, " ")
|
|
for _, part := range parts {
|
|
if strings.HasPrefix(part, "dbname=") {
|
|
return strings.TrimPrefix(part, "dbname=")
|
|
}
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
// MaskPassword маскирует пароль в DSN строке для безопасного логирования
|
|
func MaskPassword(dsn string) string {
|
|
// Простая реализация - заменяет пароль на ***
|
|
parts := strings.Split(dsn, " ")
|
|
for i, part := range parts {
|
|
if strings.HasPrefix(part, "password=") {
|
|
parts[i] = "password=***"
|
|
break
|
|
}
|
|
}
|
|
return strings.Join(parts, " ")
|
|
} |