forked from mirrors/gotosocial
tidy up database creation logic a bit (#317)
This commit is contained in:
parent
f3e36de78a
commit
38d73f0316
1 changed files with 75 additions and 43 deletions
|
@ -46,8 +46,7 @@ import (
|
||||||
"github.com/uptrace/bun/dialect/sqlitedialect"
|
"github.com/uptrace/bun/dialect/sqlitedialect"
|
||||||
"github.com/uptrace/bun/migrate"
|
"github.com/uptrace/bun/migrate"
|
||||||
|
|
||||||
// blank import for the sqlite driver for bun
|
"modernc.org/sqlite"
|
||||||
_ "modernc.org/sqlite"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -107,67 +106,38 @@ func doMigration(ctx context.Context, db *bun.DB) error {
|
||||||
// NewBunDBService returns a bunDB derived from the provided config, which implements the go-fed DB interface.
|
// NewBunDBService returns a bunDB derived from the provided config, which implements the go-fed DB interface.
|
||||||
// Under the hood, it uses https://github.com/uptrace/bun to create and maintain a database connection.
|
// Under the hood, it uses https://github.com/uptrace/bun to create and maintain a database connection.
|
||||||
func NewBunDBService(ctx context.Context, c *config.Config) (db.DB, error) {
|
func NewBunDBService(ctx context.Context, c *config.Config) (db.DB, error) {
|
||||||
var sqldb *sql.DB
|
|
||||||
var conn *DBConn
|
var conn *DBConn
|
||||||
|
var err error
|
||||||
// depending on the database type we're trying to create, we need to use a different driver...
|
|
||||||
switch strings.ToLower(c.DBConfig.Type) {
|
switch strings.ToLower(c.DBConfig.Type) {
|
||||||
case dbTypePostgres:
|
case dbTypePostgres:
|
||||||
// POSTGRES
|
conn, err = pgConn(ctx, c)
|
||||||
opts, err := deriveBunDBPGOptions(c)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not create bundb postgres options: %s", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
sqldb = stdlib.OpenDB(*opts)
|
|
||||||
tweakConnectionValues(sqldb)
|
|
||||||
conn = WrapDBConn(bun.NewDB(sqldb, pgdialect.New()))
|
|
||||||
case dbTypeSqlite:
|
case dbTypeSqlite:
|
||||||
// SQLITE
|
conn, err = sqliteConn(ctx, c)
|
||||||
|
|
||||||
// Drop anything fancy from DB address
|
|
||||||
c.DBConfig.Address = strings.Split(c.DBConfig.Address, "?")[0]
|
|
||||||
c.DBConfig.Address = strings.TrimPrefix(c.DBConfig.Address, "file:")
|
|
||||||
|
|
||||||
// Append our own SQLite preferences
|
|
||||||
c.DBConfig.Address = "file:" + c.DBConfig.Address + "?cache=shared"
|
|
||||||
|
|
||||||
// Open new DB instance
|
|
||||||
var err error
|
|
||||||
sqldb, err = sql.Open("sqlite", c.DBConfig.Address)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not open sqlite db: %s", err)
|
return nil, err
|
||||||
}
|
|
||||||
tweakConnectionValues(sqldb)
|
|
||||||
conn = WrapDBConn(bun.NewDB(sqldb, sqlitedialect.New()))
|
|
||||||
|
|
||||||
if c.DBConfig.Address == "file::memory:?cache=shared" {
|
|
||||||
logrus.Warn("sqlite in-memory database should only be used for debugging")
|
|
||||||
|
|
||||||
// don't close connections on disconnect -- otherwise
|
|
||||||
// the SQLite database will be deleted when there
|
|
||||||
// are no active connections
|
|
||||||
sqldb.SetConnMaxLifetime(0)
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("database type %s not supported for bundb", strings.ToLower(c.DBConfig.Type))
|
return nil, fmt.Errorf("database type %s not supported for bundb", strings.ToLower(c.DBConfig.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add a hook to just log queries and the time they take
|
||||||
|
// only do this for trace logging where performance isn't 1st concern
|
||||||
if logrus.GetLevel() >= logrus.TraceLevel {
|
if logrus.GetLevel() >= logrus.TraceLevel {
|
||||||
// add a hook to just log queries and the time they take
|
|
||||||
conn.DB.AddQueryHook(newDebugQueryHook())
|
conn.DB.AddQueryHook(newDebugQueryHook())
|
||||||
}
|
}
|
||||||
|
|
||||||
// actually *begin* the connection so that we can tell if the db is there and listening
|
// table registration is needed for many-to-many, see:
|
||||||
if err := conn.Ping(); err != nil {
|
// https://bun.uptrace.dev/orm/many-to-many-relation/
|
||||||
return nil, fmt.Errorf("db connection error: %s", err)
|
|
||||||
}
|
|
||||||
logrus.Info("connected to database")
|
|
||||||
|
|
||||||
for _, t := range registerTables {
|
for _, t := range registerTables {
|
||||||
// https://bun.uptrace.dev/orm/many-to-many-relation/
|
|
||||||
conn.RegisterModel(t)
|
conn.RegisterModel(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// perform any pending database migrations: this includes
|
||||||
|
// the very first 'migration' on startup which just creates
|
||||||
|
// necessary tables
|
||||||
if err := doMigration(ctx, conn.DB); err != nil {
|
if err := doMigration(ctx, conn.DB); err != nil {
|
||||||
return nil, fmt.Errorf("db migration error: %s", err)
|
return nil, fmt.Errorf("db migration error: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -232,6 +202,68 @@ func NewBunDBService(ctx context.Context, c *config.Config) (db.DB, error) {
|
||||||
return ps, nil
|
return ps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sqliteConn(ctx context.Context, c *config.Config) (*DBConn, error) {
|
||||||
|
// Drop anything fancy from DB address
|
||||||
|
c.DBConfig.Address = strings.Split(c.DBConfig.Address, "?")[0]
|
||||||
|
c.DBConfig.Address = strings.TrimPrefix(c.DBConfig.Address, "file:")
|
||||||
|
|
||||||
|
// Append our own SQLite preferences
|
||||||
|
c.DBConfig.Address = "file:" + c.DBConfig.Address + "?cache=shared"
|
||||||
|
|
||||||
|
// Open new DB instance
|
||||||
|
sqldb, err := sql.Open("sqlite", c.DBConfig.Address)
|
||||||
|
if err != nil {
|
||||||
|
if errWithCode, ok := err.(*sqlite.Error); ok {
|
||||||
|
err = errors.New(sqlite.ErrorCodeString[errWithCode.Code()])
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("could not open sqlite db: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tweakConnectionValues(sqldb)
|
||||||
|
|
||||||
|
if c.DBConfig.Address == "file::memory:?cache=shared" {
|
||||||
|
logrus.Warn("sqlite in-memory database should only be used for debugging")
|
||||||
|
// don't close connections on disconnect -- otherwise
|
||||||
|
// the SQLite database will be deleted when there
|
||||||
|
// are no active connections
|
||||||
|
sqldb.SetConnMaxLifetime(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn := WrapDBConn(bun.NewDB(sqldb, sqlitedialect.New()))
|
||||||
|
|
||||||
|
// ping to check the db is there and listening
|
||||||
|
if err := conn.PingContext(ctx); err != nil {
|
||||||
|
if errWithCode, ok := err.(*sqlite.Error); ok {
|
||||||
|
err = errors.New(sqlite.ErrorCodeString[errWithCode.Code()])
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("sqlite ping: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Info("connected to SQLITE database")
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func pgConn(ctx context.Context, c *config.Config) (*DBConn, error) {
|
||||||
|
opts, err := deriveBunDBPGOptions(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not create bundb postgres options: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sqldb := stdlib.OpenDB(*opts)
|
||||||
|
|
||||||
|
tweakConnectionValues(sqldb)
|
||||||
|
|
||||||
|
conn := WrapDBConn(bun.NewDB(sqldb, pgdialect.New()))
|
||||||
|
|
||||||
|
// ping to check the db is there and listening
|
||||||
|
if err := conn.PingContext(ctx); err != nil {
|
||||||
|
return nil, fmt.Errorf("postgres ping: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Info("connected to POSTGRES database")
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
HANDY STUFF
|
HANDY STUFF
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue