2024-03-12 22:39:18 +00:00
|
|
|
package migrations
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2024-03-14 12:33:52 +00:00
|
|
|
"log/slog"
|
2024-03-12 22:39:18 +00:00
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"git.sr.ht/~ashkeel/strimertul/database"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
SchemaKey = "strimertul/schema-version"
|
|
|
|
SchemaVersion = 4
|
|
|
|
)
|
|
|
|
|
|
|
|
// GetCurrentSchemaVersion returns the current schema version
|
|
|
|
// from the database, or 0 if it's not set (v3.x.x or earlier)
|
|
|
|
func GetCurrentSchemaVersion(db database.Database) (int, error) {
|
|
|
|
versionStr, err := db.GetKey(SchemaKey)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, database.ErrEmptyKey) {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if versionStr == "" {
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return strconv.Atoi(versionStr)
|
|
|
|
}
|
|
|
|
|
2024-03-14 12:33:52 +00:00
|
|
|
func Run(driver database.Driver, db database.Database, logger *slog.Logger) (err error) {
|
2024-03-12 22:39:18 +00:00
|
|
|
// Make a backup of the database
|
|
|
|
var buffer bytes.Buffer
|
|
|
|
if err = driver.Backup(&buffer); err != nil {
|
2024-03-14 12:33:52 +00:00
|
|
|
return fmt.Errorf("failed to backup database: %w", err)
|
2024-03-12 22:39:18 +00:00
|
|
|
}
|
|
|
|
// Restore the backup if an error occurs
|
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
|
|
|
restoreErr := driver.Restore(bytes.NewReader(buffer.Bytes()))
|
|
|
|
if restoreErr != nil {
|
2024-03-14 12:33:52 +00:00
|
|
|
logger.Error("Failed to restore database from backup", "error", restoreErr)
|
2024-03-12 22:39:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Get the current schema version
|
|
|
|
var currentVersion int
|
|
|
|
currentVersion, err = GetCurrentSchemaVersion(db)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Migrate from v3.x.x to v4.0.0
|
|
|
|
if currentVersion < 4 {
|
|
|
|
if err = migrateToV4(db, logger); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the new schema version
|
|
|
|
if err = db.PutKey(SchemaKey, strconv.Itoa(SchemaVersion)); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|