package database import ( "fmt" "net" "os" "time" "go.uber.org/zap" "gorm.io/driver/mysql" "gorm.io/driver/sqlite" "gorm.io/gorm" "moul.io/zapgorm2" ) type Database struct { Host string User string Password string Database string } const Storage = "storage/" func init() { os.Mkdir(Storage, os.ModePerm) } func (d *Database) tryDbConnection() { i := 1 total := 20 for i <= total { ln, err := net.DialTimeout("tcp", d.Host, 1*time.Second) if err != nil { if i == total { zap.L().Fatal("Failed connecting to database", zap.Int("attempt", i)) } zap.L().Warn("Connecting to database", zap.Int("attempt", i)) time.Sleep(2 * time.Second) i++ } else { _ = ln.Close() zap.L().Info("Connected to database", zap.Int("attempt", i)) i = total + 1 } } } func (d *Database) initializeMySql(conf *gorm.Config) *gorm.DB { var err error d.tryDbConnection() dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", d.User, d.Password, d.Host, d.Database, ) orm, err := gorm.Open(mysql.Open(dsn), conf) if err != nil { zap.L().Error(err.Error()) } return orm } func (d *Database) initializeSqLite(conf *gorm.Config) *gorm.DB { var err error orm, err := gorm.Open(sqlite.Open(Storage+"db.sqlite?_pragma=foreign_keys(1)"), conf) if err != nil { zap.L().Error(err.Error()) } return orm } func NewDatabaseConnection(d *Database) *gorm.DB { logger := zapgorm2.New(zap.L()) conf := &gorm.Config{Logger: logger, PrepareStmt: true} if d.Host == "" { return d.initializeSqLite(conf) } return d.initializeMySql(conf) }