2020-03-27 23:02:36 +00:00
|
|
|
package database
|
|
|
|
|
|
|
|
import (
|
2020-04-06 05:37:22 +00:00
|
|
|
"net/url"
|
2020-03-27 23:02:36 +00:00
|
|
|
"path/filepath"
|
2020-04-06 05:37:22 +00:00
|
|
|
"strings"
|
2020-03-30 23:05:53 +00:00
|
|
|
"sync"
|
2020-04-06 05:37:22 +00:00
|
|
|
|
2020-03-30 23:05:53 +00:00
|
|
|
u "git.eeqj.de/sneak/goutil"
|
2020-04-06 05:37:22 +00:00
|
|
|
"github.com/golang/groupcache/lru"
|
|
|
|
"github.com/jinzhu/gorm"
|
|
|
|
_ "github.com/jinzhu/gorm/dialects/postgres"
|
2020-03-27 23:02:36 +00:00
|
|
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
)
|
|
|
|
|
2020-04-05 01:17:35 +00:00
|
|
|
const cacheEntries = 1000000
|
|
|
|
|
|
|
|
// Manager coordinates database and cache reads and writes
|
2020-03-27 23:02:36 +00:00
|
|
|
type Manager struct {
|
2020-03-30 23:05:53 +00:00
|
|
|
db *gorm.DB
|
|
|
|
cachelock sync.Mutex
|
2020-04-05 01:17:35 +00:00
|
|
|
recentlyInsertedTootHashCache *lru.Cache
|
2020-03-27 23:02:36 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 01:17:35 +00:00
|
|
|
// New creates new Manager
|
2020-03-27 23:02:36 +00:00
|
|
|
func New() *Manager {
|
|
|
|
m := new(Manager)
|
|
|
|
m.init()
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Manager) init() {
|
2020-04-06 05:37:22 +00:00
|
|
|
m.open(viper.GetString("DBURL"))
|
2020-03-30 23:05:53 +00:00
|
|
|
// breaks stuff, do not use:
|
|
|
|
//m.db.SingularTable(true)
|
2020-03-27 23:46:47 +00:00
|
|
|
m.db.LogMode(false)
|
|
|
|
if viper.GetBool("Debug") {
|
|
|
|
m.db.LogMode(true)
|
|
|
|
}
|
2020-04-05 01:17:35 +00:00
|
|
|
m.recentlyInsertedTootHashCache = lru.New(cacheEntries)
|
2020-03-27 23:02:36 +00:00
|
|
|
}
|
|
|
|
|
2020-04-06 05:37:22 +00:00
|
|
|
func (m *Manager) open(dbURL string) {
|
2020-03-27 23:02:36 +00:00
|
|
|
log.Info().Msg("opening database")
|
2020-04-06 05:37:22 +00:00
|
|
|
dsn, err := url.Parse(dbURL)
|
2020-03-27 23:02:36 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Panic().
|
|
|
|
Err(err).
|
2020-04-06 05:37:22 +00:00
|
|
|
Msg("error parsing dbURL")
|
2020-03-27 23:02:36 +00:00
|
|
|
}
|
2020-04-06 05:37:22 +00:00
|
|
|
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:
|
2020-03-27 23:02:36 +00:00
|
|
|
log.Panic().
|
2020-04-06 05:37:22 +00:00
|
|
|
Str("driver", dsn.Scheme).
|
|
|
|
Msg("unsupported driver in database url, must be 'postgres' or 'sqlite'")
|
2020-03-27 23:02:36 +00:00
|
|
|
}
|
2020-04-06 05:37:22 +00:00
|
|
|
|
2020-03-27 23:02:36 +00:00
|
|
|
m.doMigrations()
|
|
|
|
}
|