mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 14:21:14 +00:00
scmigrate: ensure target key is correctly renamed (#8276)
Prior to v0.35, the keys for seen-commit records included the applicable height. In v0.35 and beyond, we only keep the record for the latest height, and its key does not include the height. Update the seen-commit migration to ensure that the record we retain after migration is correctly renamed to omit the height from its key. Update the test cases to check for this condition after migrating.
This commit is contained in:
@@ -73,8 +73,6 @@ func sortMigrations(scData []toMigrate) {
|
||||
})
|
||||
}
|
||||
|
||||
func getMigrationsToDelete(in []toMigrate) []toMigrate { return in[1:] }
|
||||
|
||||
func getAllSeenCommits(ctx context.Context, db dbm.DB) ([]toMigrate, error) {
|
||||
scKeyPrefix := makeKeyFromPrefix(prefixSeenCommit)
|
||||
iter, err := db.Iterator(
|
||||
@@ -117,6 +115,34 @@ func getAllSeenCommits(ctx context.Context, db dbm.DB) ([]toMigrate, error) {
|
||||
return scData, nil
|
||||
}
|
||||
|
||||
func renameRecord(ctx context.Context, db dbm.DB, keep toMigrate) error {
|
||||
wantKey := makeKeyFromPrefix(prefixSeenCommit)
|
||||
if bytes.Equal(keep.key, wantKey) {
|
||||
return nil // we already did this conversion
|
||||
}
|
||||
|
||||
// This record's key has already been converted to the "new" format, we just
|
||||
// now need to trim off the tail.
|
||||
val, err := db.Get(keep.key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
batch := db.NewBatch()
|
||||
if err := batch.Delete(keep.key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := batch.Set(wantKey, val); err != nil {
|
||||
return err
|
||||
}
|
||||
werr := batch.Write()
|
||||
cerr := batch.Close()
|
||||
if werr != nil {
|
||||
return werr
|
||||
}
|
||||
return cerr
|
||||
}
|
||||
|
||||
func deleteRecords(ctx context.Context, db dbm.DB, scData []toMigrate) error {
|
||||
// delete all the remaining stale values in a single batch
|
||||
batch := db.NewBatch()
|
||||
@@ -141,20 +167,29 @@ func Migrate(ctx context.Context, db dbm.DB) error {
|
||||
scData, err := getAllSeenCommits(ctx, db)
|
||||
if err != nil {
|
||||
return fmt.Errorf("sourcing tasks to migrate: %w", err)
|
||||
} else if len(scData) == 0 {
|
||||
return nil // nothing to do
|
||||
}
|
||||
|
||||
// sort earliest->latest commits.
|
||||
// Sort commits in decreasing order of height.
|
||||
sortMigrations(scData)
|
||||
|
||||
// trim the one we want to save:
|
||||
scData = getMigrationsToDelete(scData)
|
||||
// Keep and rename the newest seen commit, delete the rest.
|
||||
// In TM < v0.35 we kept a last-seen commit for each height; in v0.35 we
|
||||
// retain only the latest.
|
||||
keep, remove := scData[0], scData[1:]
|
||||
|
||||
if len(scData) <= 1 {
|
||||
if err := renameRecord(ctx, db, keep); err != nil {
|
||||
return fmt.Errorf("renaming seen commit record: %w", err)
|
||||
}
|
||||
|
||||
if len(remove) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// write the migration (remove )
|
||||
if err := deleteRecords(ctx, db, scData); err != nil {
|
||||
// Remove any older seen commits. Prior to v0.35, we kept these records for
|
||||
// all heights, but v0.35 keeps only the latest.
|
||||
if err := deleteRecords(ctx, db, remove); err != nil {
|
||||
return fmt.Errorf("writing data: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package scmigrate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
@@ -104,15 +105,6 @@ func TestMigrations(t *testing.T) {
|
||||
assertWellOrderedMigrations(t, testData)
|
||||
})
|
||||
})
|
||||
t.Run("GetMigrationsToDelete", func(t *testing.T) {
|
||||
for i := 1; i < 100; i++ {
|
||||
data := appendRandomMigrations([]toMigrate{}, i)
|
||||
toMigrate := getMigrationsToDelete(data)
|
||||
if len(data) != len(toMigrate)+1 {
|
||||
t.Fatalf("migration prep did not save one document [original=%d migrations=%d]", len(data), len(toMigrate))
|
||||
}
|
||||
}
|
||||
})
|
||||
t.Run("InvalidMigrations", func(t *testing.T) {
|
||||
if _, err := makeToMigrate(nil); err == nil {
|
||||
t.Fatal("should error for nil migrations")
|
||||
@@ -156,18 +148,24 @@ func TestMigrations(t *testing.T) {
|
||||
// safe to rerun
|
||||
t.Run(test, func(t *testing.T) {
|
||||
if err := Migrate(ctx, db); err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatalf("Migration failed: %v", err)
|
||||
}
|
||||
|
||||
post, err := getAllSeenCommits(ctx, db)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
t.Fatalf("Fetching seen commits: %v", err)
|
||||
}
|
||||
|
||||
if len(post) != 1 {
|
||||
t.Fatal("migration was not successful")
|
||||
t.Fatalf("Wrong number of commits: got %d, wanted 1", len(post))
|
||||
}
|
||||
if post[0].commit.Height != latestHeight {
|
||||
t.Fatal("migration did not save correct document")
|
||||
|
||||
wantKey := makeKeyFromPrefix(prefixSeenCommit)
|
||||
if !bytes.Equal(post[0].key, wantKey) {
|
||||
t.Errorf("Seen commit key: got %x, want %x", post[0].key, wantKey)
|
||||
}
|
||||
if got := post[0].commit.Height; got != latestHeight {
|
||||
t.Fatalf("Wrong commit height after migration: got %d, wanted %d", got, latestHeight)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user