package database import ( "net/url" "path/filepath" "strings" "sync" u "git.eeqj.de/sneak/goutil" "github.com/golang/groupcache/lru" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/sqlite" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) const cacheEntries = 1000000 // Manager coordinates database and cache reads and writes type Manager struct { db *gorm.DB cachelock sync.Mutex recentlyInsertedTootHashCache *lru.Cache } // New creates new Manager func New() *Manager { m := new(Manager) m.init() return m } func (m *Manager) init() { m.open(viper.GetString("DBURL")) // breaks stuff, do not use: //m.db.SingularTable(true) m.db.LogMode(false) if viper.GetBool("Debug") { m.db.LogMode(true) } m.recentlyInsertedTootHashCache = lru.New(cacheEntries) } func (m *Manager) open(dbURL string) { log.Info().Msg("opening database") dsn, err := url.Parse(dbURL) if err != nil { log.Panic(). Err(err). Msg("error parsing dbURL") } log.Info(). Str("scheme", dsn.Scheme). Str("user", dsn.User.Username()). Str("host", dsn.Host). Str("db", dsn.Path). Str("args", dsn.RawQuery). Msg("db connection values") switch { case strings.HasPrefix(dbURL, "postgres://"): log.Info().Msg("using postgres db") db, err := gorm.Open("postgres", dbURL) if err != nil { log.Panic(). Err(err). Msg("failed to open database") } m.db = db case strings.HasPrefix(dbURL, "sqlite://"): log.Info().Msg("using sqlite db") if !strings.HasSuffix(dbURL, ":memory:") { dirname := filepath.Dir(strings.TrimPrefix(dbURL, "sqlite://")) err := u.Mkdirp(dirname) if err != nil { log.Panic(). Err(err). Msg("db path error") } } db, err := gorm.Open("sqlite3", strings.TrimPrefix(dbURL, "sqlite://")) if err != nil { log.Panic(). Err(err). Str("dbURL", dbURL). Msg("failed to open database") } m.db = db default: log.Panic(). Str("driver", dsn.Scheme). Msg("unsupported driver in database url, must be 'postgres' or 'sqlite'") } m.doMigrations() }