mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-12 22:59:38 +02:00
graph/db: add SQL migration function and test framework
In this commit, the basic framework for the graph SQL migration is added. This sets us up for the commits to follow which will add migration logic for each table in the graph commit by commit.
This commit is contained in:
62
graph/db/sql_migration.go
Normal file
62
graph/db/sql_migration.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
)
|
||||
|
||||
// MigrateGraphToSQL migrates the graph store from a KV backend to a SQL
|
||||
// backend.
|
||||
//
|
||||
// NOTE: this is currently not called from any code path. It is called via tests
|
||||
// only for now and will be called from the main lnd binary once the
|
||||
// migration is fully implemented and tested.
|
||||
func MigrateGraphToSQL(_ context.Context, kvBackend kvdb.Backend,
|
||||
_ SQLQueries, _ chainhash.Hash) error {
|
||||
|
||||
log.Infof("Starting migration of the graph store from KV to SQL")
|
||||
t0 := time.Now()
|
||||
|
||||
// Check if there is a graph to migrate.
|
||||
graphExists, err := checkGraphExists(kvBackend)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check graph existence: %w", err)
|
||||
}
|
||||
if !graphExists {
|
||||
log.Infof("No graph found in KV store, skipping the migration")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Infof("Finished migration of the graph store from KV to SQL in %v",
|
||||
time.Since(t0))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkGraphExists checks if the graph exists in the KV backend.
|
||||
func checkGraphExists(db kvdb.Backend) (bool, error) {
|
||||
// Check if there is even a graph to migrate.
|
||||
err := db.View(func(tx kvdb.RTx) error {
|
||||
// Check for the existence of the node bucket which is a top
|
||||
// level bucket that would have been created on the initial
|
||||
// creation of the graph store.
|
||||
nodes := tx.ReadBucket(nodeBucket)
|
||||
if nodes == nil {
|
||||
return ErrGraphNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}, func() {})
|
||||
if errors.Is(err, ErrGraphNotFound) {
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
82
graph/db/sql_migration_test.go
Normal file
82
graph/db/sql_migration_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
//go:build test_db_postgres || test_db_sqlite
|
||||
|
||||
package graphdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var testChain = *chaincfg.MainNetParams.GenesisHash
|
||||
|
||||
// TestMigrateGraphToSQL tests various deterministic cases that we want to test
|
||||
// for to ensure that our migration from a graph store backed by a KV DB to a
|
||||
// SQL database works as expected. At the end of each test, the DBs are compared
|
||||
// and expected to have the exact same data in them.
|
||||
func TestMigrateGraphToSQL(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
write func(t *testing.T, db *KVStore, object any)
|
||||
objects []any
|
||||
expGraphStats graphStats
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Set up our source kvdb DB.
|
||||
kvDB := setUpKVStore(t)
|
||||
|
||||
// Write the test objects to the kvdb store.
|
||||
for _, object := range test.objects {
|
||||
test.write(t, kvDB, object)
|
||||
}
|
||||
|
||||
// Set up our destination SQL DB.
|
||||
sql, ok := NewTestDB(t).(*SQLStore)
|
||||
require.True(t, ok)
|
||||
|
||||
// Run the migration.
|
||||
err := MigrateGraphToSQL(
|
||||
ctx, kvDB.db, sql.db, testChain,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate that the two databases are now in sync.
|
||||
assertInSync(t, kvDB, sql, test.expGraphStats)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// graphStats holds expected statistics about the graph after migration.
|
||||
type graphStats struct {
|
||||
}
|
||||
|
||||
// assertInSync checks that the KVStore and SQLStore both contain the same
|
||||
// graph data after migration.
|
||||
func assertInSync(_ *testing.T, _ *KVStore, _ *SQLStore, stats graphStats) {
|
||||
}
|
||||
|
||||
// setUpKVStore initializes a new KVStore for testing.
|
||||
func setUpKVStore(t *testing.T) *KVStore {
|
||||
kvDB, cleanup, err := kvdb.GetTestBackend(t.TempDir(), "graph")
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(cleanup)
|
||||
|
||||
kvStore, err := NewKVStore(kvDB)
|
||||
require.NoError(t, err)
|
||||
|
||||
return kvStore
|
||||
}
|
Reference in New Issue
Block a user