sql: Refactor use of tables
This commit is contained in:
parent
85fe5b5c5a
commit
73d821e320
19 changed files with 191 additions and 83 deletions
|
|
@ -14,6 +14,7 @@ import (
|
|||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/timex"
|
||||
)
|
||||
|
|
@ -44,8 +45,13 @@ func (sql *SQL) Exec(query string, args ...interface{}) error {
|
|||
// ========== connection via gorm ==========
|
||||
//
|
||||
|
||||
// QueryTable returns a gorm.DB to connect to the provided distillery database table
|
||||
func (sql *SQL) QueryTable(ctx context.Context, silent bool, table string) (*gorm.DB, error) {
|
||||
// QueryTable returns a gorm.DB to connect to the provided table of the given model
|
||||
func (sql *SQL) QueryTable(ctx context.Context, table component.Table) (*gorm.DB, error) {
|
||||
return sql.queryTable(ctx, false, table.TableInfo().Name)
|
||||
}
|
||||
|
||||
// queryTable returns a gorm.DB to connect to the provided distillery database table
|
||||
func (sql *SQL) queryTable(ctx context.Context, silent bool, table string) (*gorm.DB, error) {
|
||||
conn, err := sql.connect(sql.Config.DistilleryDatabase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -88,7 +94,8 @@ func (sql *SQL) QueryTable(ctx context.Context, silent bool, table string) (*gor
|
|||
func (sql *SQL) WaitQueryTable(ctx context.Context) error {
|
||||
// TODO: Establish a convention on when to wait for this!
|
||||
return timex.TickUntilFunc(func(time.Time) bool {
|
||||
_, err := sql.QueryTable(ctx, true, models.InstanceTable)
|
||||
// TODO: Use a different table here
|
||||
_, err := sql.queryTable(ctx, true, models.InstanceTable)
|
||||
return err == nil
|
||||
}, ctx, sql.PollInterval)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,23 @@ func newGormLogger() logger.Interface {
|
|||
}
|
||||
}
|
||||
|
||||
// logLevelMap is the default
|
||||
var logLevelMap = map[logger.LogLevel]zerolog.Level{
|
||||
logger.Silent: zerolog.Disabled,
|
||||
logger.Error: zerolog.ErrorLevel,
|
||||
logger.Warn: zerolog.WarnLevel,
|
||||
logger.Info: zerolog.DebugLevel,
|
||||
logger.Info + 1: zerolog.TraceLevel,
|
||||
}
|
||||
|
||||
func (*gormLogger) NewEvent(ctx context.Context, level logger.LogLevel) *zerolog.Event {
|
||||
zl, ok := logLevelMap[level]
|
||||
if !ok {
|
||||
zl = zerolog.NoLevel
|
||||
}
|
||||
return zerolog.Ctx(ctx).WithLevel(zl)
|
||||
}
|
||||
|
||||
func (gl *gormLogger) LogMode(level logger.LogLevel) logger.Interface {
|
||||
new := *gl
|
||||
new.Level = level
|
||||
|
|
@ -35,19 +52,19 @@ func (gl *gormLogger) Info(ctx context.Context, format string, v ...interface{})
|
|||
if gl.Level < logger.Info {
|
||||
return
|
||||
}
|
||||
zerolog.Ctx(ctx).Info().Msgf(format, v...)
|
||||
gl.NewEvent(ctx, logger.Info).Msgf(format, v...)
|
||||
}
|
||||
func (gl *gormLogger) Warn(ctx context.Context, format string, v ...interface{}) {
|
||||
if gl.Level < logger.Warn {
|
||||
return
|
||||
}
|
||||
zerolog.Ctx(ctx).Warn().Msgf(format, v...)
|
||||
gl.NewEvent(ctx, logger.Warn).Msgf(format, v...)
|
||||
}
|
||||
func (gl *gormLogger) Error(ctx context.Context, format string, v ...interface{}) {
|
||||
if gl.Level < logger.Error {
|
||||
return
|
||||
}
|
||||
zerolog.Ctx(ctx).Error().Msgf(format, v...)
|
||||
gl.NewEvent(ctx, logger.Error).Msgf(format, v...)
|
||||
}
|
||||
func (gl *gormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
|
||||
if gl.Level < logger.Silent {
|
||||
|
|
@ -60,15 +77,15 @@ func (gl *gormLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql
|
|||
sql, rows := fc()
|
||||
src := utils.FileWithLineNum()
|
||||
|
||||
zerolog.Ctx(ctx).Err(err).Str("src", src).Int64("rows", rows).Dur("elapsed", elapsed).Str("sql", sql).Msg("GORM")
|
||||
gl.NewEvent(ctx, logger.Error).Str("src", src).Int64("rows", rows).Dur("elapsed", elapsed).Str("sql", sql).Msg("GORM")
|
||||
case elapsed > gl.SlowThreshold && gl.SlowThreshold != 0 && gl.Level >= logger.Warn:
|
||||
sql, rows := fc()
|
||||
src := utils.FileWithLineNum()
|
||||
zerolog.Ctx(ctx).Warn().Str("src", src).Int64("rows", rows).Dur("elapsed", elapsed).Str("sql", sql).Msgf("GORM: Slow SQL >= ", gl.SlowThreshold)
|
||||
gl.NewEvent(ctx, logger.Warn).Str("src", src).Int64("rows", rows).Dur("elapsed", elapsed).Str("sql", sql).Msgf("GORM: Slow SQL >= ", gl.SlowThreshold)
|
||||
case gl.Level == logger.Info:
|
||||
sql, rows := fc()
|
||||
src := utils.FileWithLineNum()
|
||||
|
||||
zerolog.Ctx(ctx).Debug().Str("src", src).Int64("rows", rows).Dur("elapsed", elapsed).Str("sql", sql).Msg("GORM")
|
||||
gl.NewEvent(ctx, logger.Info+1).Str("src", src).Int64("rows", rows).Dur("elapsed", elapsed).Str("sql", sql).Msg("GORM")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ import (
|
|||
|
||||
type SQL struct {
|
||||
component.Base
|
||||
Dependencies struct {
|
||||
Tables []component.Table
|
||||
}
|
||||
|
||||
ServerURL string // upstream server url
|
||||
|
||||
|
|
|
|||
39
internal/dis/component/sql/tables.go
Normal file
39
internal/dis/component/sql/tables.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||
"github.com/tkw1536/goprogram/lib/reflectx"
|
||||
)
|
||||
|
||||
// This file defines additional tables used by multiple components
|
||||
|
||||
type InstanceTable struct {
|
||||
component.Base
|
||||
}
|
||||
|
||||
var (
|
||||
_ component.Table = (*InstanceTable)(nil)
|
||||
)
|
||||
|
||||
func (*InstanceTable) TableInfo() component.TableInfo {
|
||||
return component.TableInfo{
|
||||
Model: reflectx.TypeOf[models.Instance](),
|
||||
Name: models.InstanceTable,
|
||||
}
|
||||
}
|
||||
|
||||
type LockTable struct {
|
||||
component.Base
|
||||
}
|
||||
|
||||
var (
|
||||
_ component.Table = (*LockTable)(nil)
|
||||
)
|
||||
|
||||
func (*LockTable) TableInfo() component.TableInfo {
|
||||
return component.TableInfo{
|
||||
Model: reflectx.TypeOf[models.Lock](),
|
||||
Name: models.LockTable,
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,9 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/sqle"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/timex"
|
||||
|
|
@ -76,56 +76,24 @@ func (sql *SQL) Update(ctx context.Context, progress io.Writer) error {
|
|||
|
||||
// wait for the database to come up
|
||||
logging.LogMessage(progress, ctx, "Waiting for database update to be complete")
|
||||
sql.WaitQueryTable(ctx)
|
||||
|
||||
tables := []struct {
|
||||
name string
|
||||
model any
|
||||
table string
|
||||
}{
|
||||
{
|
||||
"instance",
|
||||
&models.Instance{},
|
||||
models.InstanceTable,
|
||||
},
|
||||
{
|
||||
"metadata",
|
||||
&models.Metadatum{},
|
||||
models.MetadataTable,
|
||||
},
|
||||
{
|
||||
"snapshot",
|
||||
&models.Export{},
|
||||
models.ExportTable,
|
||||
},
|
||||
{
|
||||
"lock",
|
||||
&models.Lock{},
|
||||
models.LockTable,
|
||||
},
|
||||
{
|
||||
"users",
|
||||
&models.User{},
|
||||
models.UserTable,
|
||||
},
|
||||
{
|
||||
"grant",
|
||||
&models.Grant{},
|
||||
models.GrantTable,
|
||||
},
|
||||
if err := sql.WaitQueryTable(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// migrate all of the tables!
|
||||
return logging.LogOperation(func() error {
|
||||
for _, table := range tables {
|
||||
logging.LogMessage(progress, ctx, "migrating %q table", table.name)
|
||||
db, err := sql.QueryTable(ctx, false, table.table)
|
||||
for _, table := range sql.Dependencies.Tables {
|
||||
info := table.TableInfo()
|
||||
logging.LogMessage(progress, ctx, "migrating %q table", table.Name)
|
||||
db, err := sql.queryTable(ctx, false, info.Name)
|
||||
if err != nil {
|
||||
return errSQLUnableToMigrate.WithMessageF(table.name, "unable to access table")
|
||||
return errSQLUnableToMigrate.WithMessageF(table.Name, "unable to access table")
|
||||
}
|
||||
|
||||
if err := db.AutoMigrate(table.model); err != nil {
|
||||
return errSQLUnableToMigrate.WithMessageF(table.name, err)
|
||||
tp := reflect.New(info.Model).Interface()
|
||||
|
||||
if err := db.AutoMigrate(tp); err != nil {
|
||||
return errSQLUnableToMigrate.WithMessageF(table.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue