-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CLI] Add database migration tooling
Signed-off-by: Knut Ahlers <[email protected]>
- Loading branch information
Showing
18 changed files
with
187 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package main | ||
|
||
import ( | ||
"sync" | ||
|
||
"github.com/Luzifer/twitch-bot/v3/pkg/database" | ||
"github.com/Luzifer/twitch-bot/v3/plugins" | ||
"github.com/pkg/errors" | ||
"github.com/sirupsen/logrus" | ||
"gorm.io/gorm" | ||
) | ||
|
||
var ( | ||
dbCopyFuncs = map[string]plugins.DatabaseCopyFunc{} | ||
dbCopyFuncsLock sync.Mutex | ||
) | ||
|
||
func init() { | ||
cli.Add(cliRegistryEntry{ | ||
Name: "copy-database", | ||
Description: "Copies database contents to a new storage DSN i.e. for migrating to a new DBMS", | ||
Params: []string{"<target storage-type>", "<target DSN>"}, | ||
Run: func(args []string) error { | ||
if len(args) < 3 { //nolint:gomnd // Just a count of parameters | ||
return errors.New("Usage: twitch-bot copy-database <target storage-type> <target DSN>") | ||
} | ||
|
||
// Core functions cannot register themselves, we take that for them | ||
registerDatabaseCopyFunc("core-values", db.CopyDatabase) | ||
registerDatabaseCopyFunc("permissions", accessService.CopyDatabase) | ||
registerDatabaseCopyFunc("timers", timerService.CopyDatabase) | ||
|
||
targetDB, err := database.New(args[1], args[2], cfg.StorageEncryptionPass) | ||
if err != nil { | ||
return errors.Wrap(err, "connecting to target db") | ||
} | ||
defer func() { | ||
if err := targetDB.Close(); err != nil { | ||
logrus.WithError(err).Error("closing connection to target db") | ||
} | ||
}() | ||
|
||
return errors.Wrap( | ||
targetDB.DB().Transaction(func(tx *gorm.DB) (err error) { | ||
for name, dbcf := range dbCopyFuncs { | ||
logrus.WithField("name", name).Info("running migration") | ||
if err = dbcf(db.DB(), tx); err != nil { | ||
return errors.Wrapf(err, "running DatabaseCopyFunc %q", name) | ||
} | ||
} | ||
|
||
logrus.Info("database has been copied successfully") | ||
|
||
return nil | ||
}), | ||
"copying database to target", | ||
) | ||
}, | ||
}) | ||
} | ||
|
||
func registerDatabaseCopyFunc(name string, fn plugins.DatabaseCopyFunc) { | ||
dbCopyFuncsLock.Lock() | ||
defer dbCopyFuncsLock.Unlock() | ||
|
||
dbCopyFuncs[name] = fn | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package database | ||
|
||
import ( | ||
"reflect" | ||
|
||
"github.com/pkg/errors" | ||
"gorm.io/gorm" | ||
) | ||
|
||
const copyBatchSize = 100 | ||
|
||
// CopyObjects is a helper to copy elements of a given type from the | ||
// src to the target GORM database interface | ||
func CopyObjects(src, target *gorm.DB, objects ...any) (err error) { | ||
for _, obj := range objects { | ||
copySlice := reflect.New(reflect.SliceOf(reflect.TypeOf(obj))).Elem().Addr().Interface() | ||
|
||
if err = target.AutoMigrate(obj); err != nil { | ||
return errors.Wrap(err, "applying migration to target") | ||
} | ||
|
||
if err = target.Where("1 = 1").Delete(obj).Error; err != nil { | ||
return errors.Wrap(err, "cleaning target table") | ||
} | ||
|
||
if err = src.FindInBatches(copySlice, copyBatchSize, func(tx *gorm.DB, _ int) error { | ||
if err = target.Save(copySlice).Error; err != nil { | ||
if errors.Is(err, gorm.ErrEmptySlice) { | ||
// That's fine and no reason to exit here | ||
return nil | ||
} | ||
return errors.Wrap(err, "inserting collected elements") | ||
} | ||
|
||
return nil | ||
}).Error; err != nil { | ||
return errors.Wrap(err, "batch-copying data") | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.