ghost-listmonk-connector/database/db.go
troneras ff5b39241a first commit
fixed cache

Refactoring from app router to page router

Refactoring from app router to page router

Add authentication with JWT

base ui done

protect the dashboard

added transitions

styling

type trick added

cleanup

Add enable-disable logic

add transactional emails

Improvements on delay and frontend

added description on select

implement auth with magic link

migrate to mariadb

webhook signature working

Adding async processing with queues

Implemented webhook reply functionality

Add son execution logs

update status logic

Add recent activity monitoring to sons

show son performance in dashboard

add readme

implement listmonk connector

listmonk-connector-v1

Create CODE_OF_CONDUCT.md

Create LICENSE
2024-08-21 02:09:24 +02:00

122 lines
2.9 KiB
Go

package database
import (
"database/sql"
"fmt"
"os"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/mysql"
_ "github.com/golang-migrate/migrate/v4/source/file"
"github.com/troneras/ghost-listmonk-connector/utils"
)
var db *sql.DB
func InitDB() error {
config := utils.GetConfig()
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true",
config.DBUser, config.DBPassword, config.DBHost, config.DBPort, config.DBName)
var err error
db, err = sql.Open("mysql", dsn)
if err != nil {
return fmt.Errorf("failed to open database connection: %w", err)
}
// Configure the connection pool
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(25)
db.SetConnMaxLifetime(5 * time.Minute)
if err = db.Ping(); err != nil {
return fmt.Errorf("failed to ping database: %w", err)
}
return nil
}
func GetDB() *sql.DB {
return db
}
func CloseDB() {
if db != nil {
db.Close()
}
}
func RunMigrations(direction string, steps int) error {
err := InitDB()
if err != nil {
utils.ErrorLogger.Fatalf("Failed to initialize database: %v", err)
}
defer GetDB().Close()
utils.InfoLogger.Printf("Starting migration process. Direction: %s, Steps: %d", direction, steps)
driver, err := mysql.WithInstance(db, &mysql.Config{})
if err != nil {
utils.ErrorLogger.Printf("Failed to create migration driver: %v", err)
return fmt.Errorf("failed to create migration driver: %w", err)
}
m, err := migrate.NewWithDatabaseInstance(
"file://database/migrations",
"mysql",
driver,
)
if err != nil {
utils.ErrorLogger.Printf("Failed to create migration instance: %v", err)
return fmt.Errorf("failed to create migration instance: %w", err)
}
defer func() {
srcErr, dbErr := m.Close()
if srcErr != nil {
utils.ErrorLogger.Printf("Error closing migration source: %v", srcErr)
}
if dbErr != nil {
utils.ErrorLogger.Printf("Error closing migration database: %v", dbErr)
}
}()
// Check if any migration files exist
migrations, err := os.ReadDir("database/migrations")
if err != nil {
utils.ErrorLogger.Printf("Failed to read migrations directory: %v", err)
return fmt.Errorf("failed to read migrations directory: %w", err)
}
if len(migrations) == 0 {
utils.InfoLogger.Println("No migration files found. Skipping migration process.")
return nil
}
var migrationErr error
switch direction {
case "up":
if steps > 0 {
migrationErr = m.Steps(steps)
} else {
migrationErr = m.Up()
}
case "down":
if steps > 0 {
migrationErr = m.Steps(-steps)
} else {
migrationErr = m.Down()
}
default:
return fmt.Errorf("invalid migration direction: %s", direction)
}
if migrationErr != nil && migrationErr != migrate.ErrNoChange {
utils.ErrorLogger.Printf("Error applying migrations: %v", migrationErr)
return fmt.Errorf("error applying migrations: %w", migrationErr)
}
utils.InfoLogger.Println("Migrations applied successfully")
return nil
}