3
0
mirror of https://github.com/ergochat/ergo.git synced 2025-01-22 02:04:10 +01:00

refactor schema versions to be ints, not strings

This commit is contained in:
Shivaram Lingamneni 2020-10-26 23:29:49 -04:00
parent 70b8bf75c5
commit dc456bd6a4
3 changed files with 117 additions and 115 deletions

View File

@ -24,7 +24,7 @@ const (
// 'version' of the database schema // 'version' of the database schema
keySchemaVersion = "db.version" keySchemaVersion = "db.version"
// latest schema of the db // latest schema of the db
latestDbSchema = "17" latestDbSchema = 17
keyCloakSecret = "crypto.cloak_secret" keyCloakSecret = "crypto.cloak_secret"
) )
@ -32,14 +32,11 @@ const (
type SchemaChanger func(*Config, *buntdb.Tx) error type SchemaChanger func(*Config, *buntdb.Tx) error
type SchemaChange struct { type SchemaChange struct {
InitialVersion string // the change will take this version InitialVersion int // the change will take this version
TargetVersion string // and transform it into this version TargetVersion int // and transform it into this version
Changer SchemaChanger Changer SchemaChanger
} }
// maps an initial version to a schema change capable of upgrading it
var schemaChanges map[string]SchemaChange
func checkDBReadyForInit(path string) error { func checkDBReadyForInit(path string) error {
_, err := os.Stat(path) _, err := os.Stat(path)
if err == nil { if err == nil {
@ -72,7 +69,7 @@ func initializeDB(path string) error {
err = store.Update(func(tx *buntdb.Tx) error { err = store.Update(func(tx *buntdb.Tx) error {
// set schema version // set schema version
tx.Set(keySchemaVersion, latestDbSchema, nil) tx.Set(keySchemaVersion, strconv.Itoa(latestDbSchema), nil)
tx.Set(keyCloakSecret, utils.GenerateSecretKey(), nil) tx.Set(keyCloakSecret, utils.GenerateSecretKey(), nil)
return nil return nil
}) })
@ -100,9 +97,12 @@ func openDatabaseInternal(config *Config, allowAutoupgrade bool) (db *buntdb.DB,
}() }()
// read the current version string // read the current version string
var version string var version int
err = db.View(func(tx *buntdb.Tx) error { err = db.View(func(tx *buntdb.Tx) (err error) {
version, err = tx.Get(keySchemaVersion) vStr, err := tx.Get(keySchemaVersion)
if err == nil {
version, err = strconv.Atoi(vStr)
}
return err return err
}) })
if err != nil { if err != nil {
@ -130,11 +130,11 @@ func openDatabaseInternal(config *Config, allowAutoupgrade bool) (db *buntdb.DB,
} }
} }
func performAutoUpgrade(currentVersion string, config *Config) (err error) { func performAutoUpgrade(currentVersion int, config *Config) (err error) {
path := config.Datastore.Path path := config.Datastore.Path
log.Printf("attempting to auto-upgrade schema from version %s to %s\n", currentVersion, latestDbSchema) log.Printf("attempting to auto-upgrade schema from version %d to %d\n", currentVersion, latestDbSchema)
timestamp := time.Now().UTC().Format("2006-01-02-15:04:05.000Z") timestamp := time.Now().UTC().Format("2006-01-02-15:04:05.000Z")
backupPath := fmt.Sprintf("%s.v%s.%s.bak", path, currentVersion, timestamp) backupPath := fmt.Sprintf("%s.v%d.%s.bak", path, currentVersion, timestamp)
log.Printf("making a backup of current database at %s\n", backupPath) log.Printf("making a backup of current database at %s\n", backupPath)
err = utils.CopyFile(path, backupPath) err = utils.CopyFile(path, backupPath)
if err != nil { if err != nil {
@ -164,29 +164,30 @@ func UpgradeDB(config *Config) (err error) {
} }
defer store.Close() defer store.Close()
var version string var version int
err = store.Update(func(tx *buntdb.Tx) error { err = store.Update(func(tx *buntdb.Tx) error {
for { for {
version, _ = tx.Get(keySchemaVersion) vStr, _ := tx.Get(keySchemaVersion)
change, schemaNeedsChange := schemaChanges[version] version, _ = strconv.Atoi(vStr)
if !schemaNeedsChange {
if version == latestDbSchema { if version == latestDbSchema {
// success! // success!
break break
} }
change, ok := getSchemaChange(version)
if !ok {
// unable to upgrade to the desired version, roll back // unable to upgrade to the desired version, roll back
return &utils.IncompatibleSchemaError{CurrentVersion: version, RequiredVersion: latestDbSchema} return &utils.IncompatibleSchemaError{CurrentVersion: version, RequiredVersion: latestDbSchema}
} }
log.Println("attempting to update schema from version " + version) log.Printf("attempting to update schema from version %d\n", version)
err := change.Changer(config, tx) err := change.Changer(config, tx)
if err != nil { if err != nil {
return err return err
} }
_, _, err = tx.Set(keySchemaVersion, change.TargetVersion, nil) _, _, err = tx.Set(keySchemaVersion, strconv.Itoa(change.TargetVersion), nil)
if err != nil { if err != nil {
return err return err
} }
log.Println("successfully updated schema to version " + change.TargetVersion) log.Printf("successfully updated schema to version %d\n", change.TargetVersion)
} }
return nil return nil
}) })
@ -853,93 +854,94 @@ func schemaChangeV16ToV17(config *Config, tx *buntdb.Tx) error {
return nil return nil
} }
func init() { func getSchemaChange(initialVersion int) (result SchemaChange, ok bool) {
allChanges := []SchemaChange{ for _, change := range allChanges {
if initialVersion == change.InitialVersion {
return result, true
}
}
return
}
var allChanges = []SchemaChange{
{ {
InitialVersion: "1", InitialVersion: 1,
TargetVersion: "2", TargetVersion: 2,
Changer: schemaChangeV1toV2, Changer: schemaChangeV1toV2,
}, },
{ {
InitialVersion: "2", InitialVersion: 2,
TargetVersion: "3", TargetVersion: 3,
Changer: schemaChangeV2ToV3, Changer: schemaChangeV2ToV3,
}, },
{ {
InitialVersion: "3", InitialVersion: 3,
TargetVersion: "4", TargetVersion: 4,
Changer: schemaChangeV3ToV4, Changer: schemaChangeV3ToV4,
}, },
{ {
InitialVersion: "4", InitialVersion: 4,
TargetVersion: "5", TargetVersion: 5,
Changer: schemaChangeV4ToV5, Changer: schemaChangeV4ToV5,
}, },
{ {
InitialVersion: "5", InitialVersion: 5,
TargetVersion: "6", TargetVersion: 6,
Changer: schemaChangeV5ToV6, Changer: schemaChangeV5ToV6,
}, },
{ {
InitialVersion: "6", InitialVersion: 6,
TargetVersion: "7", TargetVersion: 7,
Changer: schemaChangeV6ToV7, Changer: schemaChangeV6ToV7,
}, },
{ {
InitialVersion: "7", InitialVersion: 7,
TargetVersion: "8", TargetVersion: 8,
Changer: schemaChangeV7ToV8, Changer: schemaChangeV7ToV8,
}, },
{ {
InitialVersion: "8", InitialVersion: 8,
TargetVersion: "9", TargetVersion: 9,
Changer: schemaChangeV8ToV9, Changer: schemaChangeV8ToV9,
}, },
{ {
InitialVersion: "9", InitialVersion: 9,
TargetVersion: "10", TargetVersion: 10,
Changer: schemaChangeV9ToV10, Changer: schemaChangeV9ToV10,
}, },
{ {
InitialVersion: "10", InitialVersion: 10,
TargetVersion: "11", TargetVersion: 11,
Changer: schemaChangeV10ToV11, Changer: schemaChangeV10ToV11,
}, },
{ {
InitialVersion: "11", InitialVersion: 11,
TargetVersion: "12", TargetVersion: 12,
Changer: schemaChangeV11ToV12, Changer: schemaChangeV11ToV12,
}, },
{ {
InitialVersion: "12", InitialVersion: 12,
TargetVersion: "13", TargetVersion: 13,
Changer: schemaChangeV12ToV13, Changer: schemaChangeV12ToV13,
}, },
{ {
InitialVersion: "13", InitialVersion: 13,
TargetVersion: "14", TargetVersion: 14,
Changer: schemaChangeV13ToV14, Changer: schemaChangeV13ToV14,
}, },
{ {
InitialVersion: "14", InitialVersion: 14,
TargetVersion: "15", TargetVersion: 15,
Changer: schemaChangeV14ToV15, Changer: schemaChangeV14ToV15,
}, },
{ {
InitialVersion: "15", InitialVersion: 15,
TargetVersion: "16", TargetVersion: 16,
Changer: schemaChangeV15ToV16, Changer: schemaChangeV15ToV16,
}, },
{ {
InitialVersion: "16", InitialVersion: 16,
TargetVersion: "17", TargetVersion: 17,
Changer: schemaChangeV16ToV17, Changer: schemaChangeV16ToV17,
}, },
} }
// build the index
schemaChanges = make(map[string]SchemaChange)
for _, change := range allChanges {
schemaChanges[change.InitialVersion] = change
}
}

View File

@ -142,7 +142,7 @@ func (mysql *MySQL) fixSchemas() (err error) {
return return
} else if err == nil && schema != latestDbSchema { } else if err == nil && schema != latestDbSchema {
// TODO figure out what to do about schema changes // TODO figure out what to do about schema changes
return &utils.IncompatibleSchemaError{CurrentVersion: schema, RequiredVersion: latestDbSchema} return fmt.Errorf("incompatible schema: got %s, expected %s", schema, latestDbSchema)
} else if err != nil { } else if err != nil {
return err return err
} }

View File

@ -71,12 +71,12 @@ func SafeErrorParam(param string) string {
} }
type IncompatibleSchemaError struct { type IncompatibleSchemaError struct {
CurrentVersion string CurrentVersion int
RequiredVersion string RequiredVersion int
} }
func (err *IncompatibleSchemaError) Error() string { func (err *IncompatibleSchemaError) Error() string {
return fmt.Sprintf("Database requires update. Expected schema v%s, got v%s", err.RequiredVersion, err.CurrentVersion) return fmt.Sprintf("Database requires update. Expected schema v%d, got v%d", err.RequiredVersion, err.CurrentVersion)
} }
func NanoToTimestamp(nanotime int64) string { func NanoToTimestamp(nanotime int64) string {