2021-03-21 07:36:11 -04:00
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"gorm.io/driver/mysql"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"gorm.io/gorm/logger"
|
|
|
|
)
|
|
|
|
|
|
|
|
type SupportedDatabase string
|
|
|
|
|
|
|
|
const (
|
|
|
|
SupportedDatabaseMySQL SupportedDatabase = "mysql"
|
|
|
|
SupportedDatabaseSQLite SupportedDatabase = "sqlite"
|
|
|
|
)
|
|
|
|
|
|
|
|
type DatabaseConfig struct {
|
|
|
|
Typ SupportedDatabase `yaml:"typ" envconfig:"DATABASE_TYPE"` //mysql or sqlite
|
|
|
|
Host string `yaml:"host" envconfig:"DATABASE_HOST"`
|
|
|
|
Port int `yaml:"port" envconfig:"DATABASE_PORT"`
|
|
|
|
Database string `yaml:"database" envconfig:"DATABASE_NAME"` // On SQLite: the database file-path, otherwise the database name
|
|
|
|
User string `yaml:"user" envconfig:"DATABASE_USERNAME"`
|
|
|
|
Password string `yaml:"password" envconfig:"DATABASE_PASSWORD"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetDatabaseForConfig(cfg *DatabaseConfig) (db *gorm.DB, err error) {
|
|
|
|
switch cfg.Typ {
|
|
|
|
case SupportedDatabaseSQLite:
|
|
|
|
if _, err = os.Stat(filepath.Dir(cfg.Database)); os.IsNotExist(err) {
|
|
|
|
if err = os.MkdirAll(filepath.Dir(cfg.Database), 0700); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2021-04-02 17:48:30 -04:00
|
|
|
db, err = gorm.Open(sqlite.Open(cfg.Database), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true})
|
2021-03-21 07:36:11 -04:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
case SupportedDatabaseMySQL:
|
|
|
|
connectionString := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Database)
|
|
|
|
db, err = gorm.Open(mysql.Open(connectionString), &gorm.Config{})
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
sqlDB, _ := db.DB()
|
|
|
|
sqlDB.SetConnMaxLifetime(time.Minute * 5)
|
|
|
|
sqlDB.SetMaxIdleConns(2)
|
|
|
|
sqlDB.SetMaxOpenConns(10)
|
|
|
|
err = sqlDB.Ping() // This DOES open a connection if necessary. This makes sure the database is accessible
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "failed to ping mysql authentication database")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enable Logger (logrus)
|
|
|
|
logCfg := logger.Config{
|
|
|
|
SlowThreshold: time.Second, // all slower than one second
|
|
|
|
Colorful: false,
|
|
|
|
LogLevel: logger.Silent, // default: log nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
if logrus.StandardLogger().GetLevel() == logrus.TraceLevel {
|
|
|
|
logCfg.LogLevel = logger.Info
|
|
|
|
logCfg.SlowThreshold = 500 * time.Millisecond // all slower than half a second
|
|
|
|
}
|
|
|
|
|
|
|
|
db.Config.Logger = logger.New(logrus.StandardLogger(), logCfg)
|
|
|
|
return
|
|
|
|
}
|
2021-04-05 18:07:05 -04:00
|
|
|
|
|
|
|
type DatabaseMigrationInfo struct {
|
|
|
|
Version string `gorm:"primaryKey"`
|
|
|
|
Applied time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
func MigrateDatabase(db *gorm.DB, version string) error {
|
|
|
|
if err := db.AutoMigrate(&DatabaseMigrationInfo{}); err != nil {
|
|
|
|
return errors.Wrap(err, "failed to migrate version database")
|
|
|
|
}
|
|
|
|
|
|
|
|
newVersion := DatabaseMigrationInfo{
|
|
|
|
Version: version,
|
|
|
|
Applied: time.Now(),
|
|
|
|
}
|
|
|
|
|
|
|
|
existingMigration := DatabaseMigrationInfo{}
|
|
|
|
db.Where("version = ?", version).FirstOrInit(&existingMigration)
|
|
|
|
|
|
|
|
if existingMigration.Version == "" {
|
|
|
|
lastVersion := DatabaseMigrationInfo{}
|
|
|
|
db.Order("applied desc, version desc").FirstOrInit(&lastVersion)
|
|
|
|
|
|
|
|
// TODO: migrate database
|
|
|
|
|
|
|
|
res := db.Create(&newVersion)
|
|
|
|
if res.Error != nil {
|
|
|
|
return errors.Wrap(res.Error, "failed to write version to database")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|