mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
Merge pull request #1326 from ViktorT-11/2026-06-dont-create-kvdb-databases-on-migration
Some checks failed
CI / frontend tests on macOS-latest (push) Has been cancelled
CI / frontend tests on ubuntu-latest (push) Has been cancelled
CI / frontend tests on windows-latest (push) Has been cancelled
CI / backend build on macOS-latest (push) Has been cancelled
CI / backend build on ubuntu-latest (push) Has been cancelled
CI / backend build on windows-latest (push) Has been cancelled
CI / cross compilation (push) Has been cancelled
CI / cross compilation-1 (push) Has been cancelled
CI / cross compilation-2 (push) Has been cancelled
CI / RPC proto compilation check (push) Has been cancelled
CI / check commits (push) Has been cancelled
CI / Sqlc check (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / run unit tests (push) Has been cancelled
CI / run unit tests-1 (push) Has been cancelled
CI / run unit tests-2 (push) Has been cancelled
CI / run unit tests-3 (push) Has been cancelled
CI / build itest binaries (push) Has been cancelled
CI / check release notes updated (push) Has been cancelled
CI / integration test (push) Has been cancelled
CI / integration test-1 (push) Has been cancelled
CI / integration test-2 (push) Has been cancelled
Some checks failed
CI / frontend tests on macOS-latest (push) Has been cancelled
CI / frontend tests on ubuntu-latest (push) Has been cancelled
CI / frontend tests on windows-latest (push) Has been cancelled
CI / backend build on macOS-latest (push) Has been cancelled
CI / backend build on ubuntu-latest (push) Has been cancelled
CI / backend build on windows-latest (push) Has been cancelled
CI / cross compilation (push) Has been cancelled
CI / cross compilation-1 (push) Has been cancelled
CI / cross compilation-2 (push) Has been cancelled
CI / RPC proto compilation check (push) Has been cancelled
CI / check commits (push) Has been cancelled
CI / Sqlc check (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / run unit tests (push) Has been cancelled
CI / run unit tests-1 (push) Has been cancelled
CI / run unit tests-2 (push) Has been cancelled
CI / run unit tests-3 (push) Has been cancelled
CI / build itest binaries (push) Has been cancelled
CI / check release notes updated (push) Has been cancelled
CI / integration test (push) Has been cancelled
CI / integration test-1 (push) Has been cancelled
CI / integration test-2 (push) Has been cancelled
[sql-75] Don't create kvdb database files in kvdb -> SQL migration if they don't exist
This commit is contained in:
commit
f78be1d0bd
3 changed files with 221 additions and 4 deletions
|
|
@ -6,12 +6,14 @@ import (
|
|||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
"github.com/golang-migrate/migrate/v4/database"
|
||||
"github.com/lightninglabs/lightning-terminal/accounts"
|
||||
"github.com/lightninglabs/lightning-terminal/db/sqlcmig6"
|
||||
"github.com/lightninglabs/lightning-terminal/db/tombstone"
|
||||
"github.com/lightninglabs/lightning-terminal/firewalldb"
|
||||
"github.com/lightninglabs/lightning-terminal/session"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
|
|
@ -88,6 +90,40 @@ func kvdbToSqlProgrammaticMigration(ctx context.Context,
|
|||
_ *sqldb.BaseDB, clock clock.Clock, q *sqlcmig6.Queries) error {
|
||||
|
||||
start := time.Now()
|
||||
|
||||
accountsActive, err := tombstone.KVDBFileExists(
|
||||
filepath.Join(accountsDir, accounts.DBFilename),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to inspect accounts kvdb: %w", err)
|
||||
}
|
||||
|
||||
sessionsActive, err := tombstone.KVDBFileExists(
|
||||
filepath.Join(networkDir, session.DBFilename),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to inspect session kvdb: %w", err)
|
||||
}
|
||||
|
||||
firewallActive, err := tombstone.KVDBFileExists(
|
||||
filepath.Join(networkDir, firewalldb.DBFilename),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to inspect rules kvdb: %w", err)
|
||||
}
|
||||
|
||||
if !accountsActive && !sessionsActive && !firewallActive {
|
||||
log.Infof("Skipping KVDB to SQL migration for all stores: " +
|
||||
"no legacy database files exist")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if basicClient == nil {
|
||||
return errors.New("lightning client is required for " +
|
||||
"migration but was nil")
|
||||
}
|
||||
|
||||
log.Infof("Starting KVDB to SQL migration for all stores")
|
||||
|
||||
accountStore, err := accounts.NewBoltStoreForMigration(
|
||||
|
|
|
|||
152
db/migsets/programmatic_migrations_test.go
Normal file
152
db/migsets/programmatic_migrations_test.go
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
package migsets
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/lightninglabs/lightning-terminal/accounts"
|
||||
"github.com/lightninglabs/lightning-terminal/db"
|
||||
"github.com/lightninglabs/lightning-terminal/db/sqlcmig6"
|
||||
"github.com/lightninglabs/lightning-terminal/firewalldb"
|
||||
"github.com/lightninglabs/lightning-terminal/session"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/sqldb/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/test/bufconn"
|
||||
)
|
||||
|
||||
// TestKVDBToSQLProgrammaticMigrationSkipsMissingStores verifies that the kvdb
|
||||
// to SQL migration does not create missing legacy kvdb files while scanning for
|
||||
// stores to migrate.
|
||||
func TestKVDBToSQLProgrammaticMigrationSkipsMissingStores(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
accountsDir := t.TempDir()
|
||||
networkDir := t.TempDir()
|
||||
|
||||
sqlStore := sqldb.NewTestSqliteDB(t, db.MakeTestMigrationSets())
|
||||
queries := sqlcmig6.NewForType(
|
||||
sqlStore.BaseDB, sqlStore.BackendType,
|
||||
)
|
||||
|
||||
err := kvdbToSqlProgrammaticMigration(
|
||||
context.Background(), nil, accountsDir, networkDir,
|
||||
sqlStore.BaseDB, clock.NewDefaultClock(), queries,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
requireNoFile(t, filepath.Join(accountsDir, accounts.DBFilename))
|
||||
requireNoFile(t, filepath.Join(networkDir, session.DBFilename))
|
||||
requireNoFile(t, filepath.Join(networkDir, firewalldb.DBFilename))
|
||||
}
|
||||
|
||||
// TestKVDBToSQLProgrammaticMigrationRunsWithOneBBoltDBFiles verifies that the
|
||||
// migration still runs when only the accounts kvdb exists, creates the missing
|
||||
// legacy files, and migrates the existing account data to SQL.
|
||||
func TestKVDBToSQLProgrammaticMigrationRunsWithOneBBoltDBFiles(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
testClock := clock.NewDefaultClock()
|
||||
accountsDir := t.TempDir()
|
||||
networkDir := t.TempDir()
|
||||
|
||||
accountStore, err := accounts.NewBoltStore(
|
||||
accountsDir, accounts.DBFilename, testClock,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = accountStore.NewAccount(ctx, 1234, time.Time{}, "acct-1")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, accountStore.Close())
|
||||
|
||||
sqlStore := sqldb.NewTestSqliteDB(t, db.MakeTestMigrationSets())
|
||||
queries := sqlcmig6.NewForType(
|
||||
sqlStore.BaseDB, sqlStore.BackendType,
|
||||
)
|
||||
|
||||
lndClient := newTestLightningClient(t)
|
||||
|
||||
err = kvdbToSqlProgrammaticMigration(
|
||||
ctx, lndClient, accountsDir, networkDir,
|
||||
sqlStore.BaseDB, testClock, queries,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
requireFileExists(t, filepath.Join(accountsDir, accounts.DBFilename))
|
||||
requireFileExists(t, filepath.Join(networkDir, session.DBFilename))
|
||||
requireFileExists(t, filepath.Join(networkDir, firewalldb.DBFilename))
|
||||
|
||||
dbAccounts, err := queries.ListAllAccounts(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, dbAccounts, 1)
|
||||
|
||||
dbSessions, err := queries.ListSessions(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, dbSessions)
|
||||
}
|
||||
|
||||
func requireNoFile(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
|
||||
_, err := os.Stat(path)
|
||||
require.ErrorIs(t, err, os.ErrNotExist)
|
||||
}
|
||||
|
||||
func requireFileExists(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
|
||||
_, err := os.Stat(path)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func newTestLightningClient(t *testing.T) lnrpc.LightningClient {
|
||||
t.Helper()
|
||||
|
||||
lis := bufconn.Listen(1024 * 1024)
|
||||
server := grpc.NewServer()
|
||||
lnrpc.RegisterLightningServer(server, &testLightningServer{})
|
||||
|
||||
go func() {
|
||||
_ = server.Serve(lis)
|
||||
}()
|
||||
|
||||
t.Cleanup(func() {
|
||||
server.Stop()
|
||||
require.NoError(t, lis.Close())
|
||||
})
|
||||
|
||||
conn, err := grpc.DialContext(
|
||||
context.Background(), "passthrough:///bufnet",
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithContextDialer(
|
||||
func(context.Context, string) (net.Conn, error) {
|
||||
return lis.Dial()
|
||||
},
|
||||
),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
require.NoError(t, conn.Close())
|
||||
})
|
||||
|
||||
return lnrpc.NewLightningClient(conn)
|
||||
}
|
||||
|
||||
type testLightningServer struct {
|
||||
lnrpc.UnimplementedLightningServer
|
||||
}
|
||||
|
||||
func (t *testLightningServer) ListMacaroonIDs(context.Context,
|
||||
*lnrpc.ListMacaroonIDsRequest) (*lnrpc.ListMacaroonIDsResponse, error) {
|
||||
|
||||
return &lnrpc.ListMacaroonIDsResponse{}, nil
|
||||
}
|
||||
|
|
@ -34,10 +34,31 @@ const (
|
|||
dbFilePermission = 0600
|
||||
)
|
||||
|
||||
// KVDBFileExists reports whether the legacy bbolt database file exists at the
|
||||
// given path. This only checks file presence and intentionally ignores any
|
||||
// tombstone state inside the database.
|
||||
func KVDBFileExists(path string) (bool, error) {
|
||||
fi, err := os.Stat(path)
|
||||
switch {
|
||||
case err == nil:
|
||||
return !fi.IsDir(), nil
|
||||
|
||||
case os.IsNotExist(err):
|
||||
return false, nil
|
||||
|
||||
default:
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// DeprecateKVDB marks the given legacy bbolt database as deprecated by
|
||||
// writing the migration tombstone marker into the specified top-level bucket.
|
||||
func DeprecateKVDB(path string, timeout time.Duration, bucketKey []byte) error {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
exists, err := KVDBFileExists(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +80,11 @@ func DeprecateKVDB(path string, timeout time.Duration, bucketKey []byte) error {
|
|||
func CheckKVDBDeprecated(path string, bucketKey []byte,
|
||||
timeout time.Duration) error {
|
||||
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
exists, err := KVDBFileExists(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -93,11 +118,15 @@ func CheckKVDBDeprecated(path string, bucketKey []byte,
|
|||
func HasActiveKVDB(path string, bucketKey []byte,
|
||||
timeout time.Duration) (bool, error) {
|
||||
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
exists, err := KVDBFileExists(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !exists {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
err := CheckKVDBDeprecated(path, bucketKey, timeout)
|
||||
err = CheckKVDBDeprecated(path, bucketKey, timeout)
|
||||
switch {
|
||||
case errors.Is(err, ErrKVDBDeprecated):
|
||||
return false, nil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue