mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
This commit adds a migration to the session store to back-fill the new session ID to group ID and group ID to session IDs indexes.
131 lines
3.8 KiB
Go
131 lines
3.8 KiB
Go
package session
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/lightninglabs/lightning-terminal/session/migration1"
|
|
"github.com/lightninglabs/lightning-terminal/session/migration2"
|
|
"go.etcd.io/bbolt"
|
|
)
|
|
|
|
// migration is a function which takes a prior outdated version of the database
|
|
// instance and mutates the key/bucket structure to arrive at a more up-to-date
|
|
// version of the database.
|
|
type migration func(tx *bbolt.Tx) error
|
|
|
|
var (
|
|
// metadataBucketKey stores all the metadata concerning the state of the
|
|
// database.
|
|
metadataBucketKey = []byte("metadata")
|
|
|
|
// dbVersionKey is the key used for storing/retrieving the current
|
|
// database version.
|
|
dbVersionKey = []byte("version")
|
|
|
|
// ErrDBReversion is returned when detecting an attempt to revert to a
|
|
// prior database version.
|
|
ErrDBReversion = errors.New("cannot revert to prior version")
|
|
|
|
// dbVersions is storing all versions of database. If the current
|
|
// version of the database doesn't match the latest version this list
|
|
// will be used for retrieving all migration function that are need to
|
|
// apply to the current db.
|
|
dbVersions = []migration{
|
|
func(tx *bbolt.Tx) error {
|
|
return migration1.MigrateSessionIDToKeyIndex(
|
|
tx, time.Now,
|
|
)
|
|
},
|
|
migration2.MigrateSessionIDToGroupIndex,
|
|
}
|
|
|
|
latestDBVersion = uint32(len(dbVersions))
|
|
)
|
|
|
|
// getDBVersion retrieves the current database version.
|
|
func getDBVersion(bucket *bbolt.Bucket) (uint32, error) {
|
|
versionBytes := bucket.Get(dbVersionKey)
|
|
if versionBytes == nil {
|
|
return 0, errors.New("database version not found")
|
|
}
|
|
return byteOrder.Uint32(versionBytes), nil
|
|
}
|
|
|
|
// setDBVersion updates the current database version.
|
|
func setDBVersion(bucket *bbolt.Bucket, version uint32) error {
|
|
var b [4]byte
|
|
byteOrder.PutUint32(b[:], version)
|
|
return bucket.Put(dbVersionKey, b[:])
|
|
}
|
|
|
|
// getBucket retrieves the bucket with the given key.
|
|
func getBucket(tx *bbolt.Tx, key []byte) (*bbolt.Bucket, error) {
|
|
bucket := tx.Bucket(key)
|
|
if bucket == nil {
|
|
return nil, fmt.Errorf("bucket \"%v\" does not exist",
|
|
string(key))
|
|
}
|
|
return bucket, nil
|
|
}
|
|
|
|
// syncVersions function is used for safe db version synchronization. It
|
|
// applies migration functions to the current database and recovers the
|
|
// previous state of db if at least one error/panic appeared during migration.
|
|
func syncVersions(db *bbolt.DB) error {
|
|
var currentVersion uint32
|
|
err := db.View(func(tx *bbolt.Tx) error {
|
|
metadata, err := getBucket(tx, metadataBucketKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
currentVersion, err = getDBVersion(metadata)
|
|
return err
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Infof("Checking for schema update: latest_version=%v, "+
|
|
"db_version=%v", latestDBVersion, currentVersion)
|
|
|
|
switch {
|
|
// If the database reports a higher version that we are aware of, the
|
|
// user is probably trying to revert to a prior version of lnd. We fail
|
|
// here to prevent reversions and unintended corruption.
|
|
case currentVersion > latestDBVersion:
|
|
log.Errorf("Refusing to revert from db_version=%d to "+
|
|
"lower version=%d", currentVersion,
|
|
latestDBVersion)
|
|
|
|
return ErrDBReversion
|
|
|
|
// If the current database version matches the latest version number,
|
|
// then we don't need to perform any migrations.
|
|
case currentVersion == latestDBVersion:
|
|
return nil
|
|
}
|
|
|
|
log.Infof("Performing database schema migration")
|
|
|
|
// Otherwise, we execute the migrations serially within a single
|
|
// database transaction to ensure the migration is atomic.
|
|
return db.Update(func(tx *bbolt.Tx) error {
|
|
for v := currentVersion; v < latestDBVersion; v++ {
|
|
log.Infof("Applying migration #%v", v+1)
|
|
|
|
migration := dbVersions[v]
|
|
if err := migration(tx); err != nil {
|
|
log.Infof("Unable to apply migration #%v", v+1)
|
|
return err
|
|
}
|
|
}
|
|
|
|
metadata, err := getBucket(tx, metadataBucketKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return setDBVersion(metadata, latestDBVersion)
|
|
})
|
|
}
|