payments/migration1: wire KV→SQL migration in the main pkg
Hook the payments KV→SQL migration into the SQL migration config. The migration is still only available when building with the build tag "test_native_sql". Moreover a tombstone protection similar to the invoice migration is added to prevent re-runningi with the KV backend once migration completes.
This commit is contained in:
4 files changed
+145
No files matched your search
@@ -51,6 +51,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/macaroons"
|
"github.com/lightningnetwork/lnd/macaroons"
|
||||||
"github.com/lightningnetwork/lnd/msgmux"
|
"github.com/lightningnetwork/lnd/msgmux"
|
||||||
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
|
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
|
||||||
|
paymentsmig1 "github.com/lightningnetwork/lnd/payments/db/migration1"
|
||||||
|
paymentsmig1sqlc "github.com/lightningnetwork/lnd/payments/db/migration1/sqlc"
|
||||||
"github.com/lightningnetwork/lnd/rpcperms"
|
"github.com/lightningnetwork/lnd/rpcperms"
|
||||||
"github.com/lightningnetwork/lnd/signal"
|
"github.com/lightningnetwork/lnd/signal"
|
||||||
"github.com/lightningnetwork/lnd/sqldb"
|
"github.com/lightningnetwork/lnd/sqldb"
|
||||||
@@ -76,6 +78,10 @@ const (
|
|||||||
// graphMigration is the version number for the graph migration
|
// graphMigration is the version number for the graph migration
|
||||||
// that migrates the KV graph to the native SQL schema.
|
// that migrates the KV graph to the native SQL schema.
|
||||||
graphMigration = 10
|
graphMigration = 10
|
||||||
|
|
||||||
|
// paymentMigration is the version number for the payments migration
|
||||||
|
// that migrates KV payments to the native SQL schema.
|
||||||
|
paymentMigration = 14
|
||||||
)
|
)
|
||||||
|
|
||||||
// GrpcRegistrar is an interface that must be satisfied by an external subserver
|
// GrpcRegistrar is an interface that must be satisfied by an external subserver
|
||||||
@@ -1153,6 +1159,31 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
paymentMig := func(tx *sqlc.Queries) error {
|
||||||
|
err := paymentsmig1.MigratePaymentsKVToSQL(
|
||||||
|
ctx,
|
||||||
|
dbs.ChanStateDB.Backend,
|
||||||
|
paymentsmig1sqlc.New(tx.GetTx()),
|
||||||
|
&paymentsmig1.SQLStoreConfig{
|
||||||
|
QueryCfg: queryCfg,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to migrate "+
|
||||||
|
"payments to SQL: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the payments bucket tombstone to
|
||||||
|
// indicate that the migration has been
|
||||||
|
// completed.
|
||||||
|
d.logger.Debugf("Setting payments bucket " +
|
||||||
|
"tombstone")
|
||||||
|
|
||||||
|
return paymentsdb.SetPaymentsBucketTombstone(
|
||||||
|
dbs.ChanStateDB.Backend,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we attach the custom migration function to
|
// Make sure we attach the custom migration function to
|
||||||
// the correct migration version.
|
// the correct migration version.
|
||||||
for i := 0; i < len(migrations); i++ {
|
for i := 0; i < len(migrations); i++ {
|
||||||
@@ -1162,11 +1193,17 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
|||||||
migrations[i].MigrationFn = invoiceMig
|
migrations[i].MigrationFn = invoiceMig
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case graphMigration:
|
case graphMigration:
|
||||||
migrations[i].MigrationFn = graphMig
|
migrations[i].MigrationFn = graphMig
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
case paymentMigration:
|
||||||
|
migrations[i].MigrationFn = paymentMig
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1265,6 +1302,27 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the payments bucket tombstone is set. If it is, we
|
||||||
|
// need to return and ask the user switch back to using the
|
||||||
|
// native SQL store.
|
||||||
|
ripPayments, err := paymentsdb.GetPaymentsBucketTombstone(
|
||||||
|
dbs.ChanStateDB.Backend,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("unable to check payments bucket "+
|
||||||
|
"tombstone: %w", err)
|
||||||
|
d.logger.Error(err)
|
||||||
|
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if ripPayments {
|
||||||
|
err = fmt.Errorf("payments bucket tombstoned, please " +
|
||||||
|
"switch back to native SQL")
|
||||||
|
d.logger.Error(err)
|
||||||
|
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
dbs.InvoiceDB = dbs.ChanStateDB
|
dbs.InvoiceDB = dbs.ChanStateDB
|
||||||
|
|
||||||
graphStore, err = graphdb.NewKVStore(
|
graphStore, err = graphdb.NewKVStore(
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package paymentsdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/kvdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// paymentsBucketTombstone is the key used to mark the payments bucket
|
||||||
|
// as permanently closed after a successful migration.
|
||||||
|
paymentsBucketTombstone = []byte("payments-tombstone")
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetPaymentsBucketTombstone sets the tombstone key in the payments bucket to
|
||||||
|
// mark the bucket as permanently closed. This prevents it from being reopened
|
||||||
|
// in the future.
|
||||||
|
func SetPaymentsBucketTombstone(db kvdb.Backend) error {
|
||||||
|
return kvdb.Update(db, func(tx kvdb.RwTx) error {
|
||||||
|
// Access the top-level payments bucket.
|
||||||
|
payments := tx.ReadWriteBucket(paymentsRootBucket)
|
||||||
|
|
||||||
|
// In case the bucket doesn't exist, because we start
|
||||||
|
// immediately with the native SQL schema, we create it as well
|
||||||
|
// to make sure the user cannot switch back to the KV store.
|
||||||
|
if payments == nil {
|
||||||
|
var err error
|
||||||
|
payments, err = tx.CreateTopLevelBucket(
|
||||||
|
paymentsRootBucket,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create payments "+
|
||||||
|
"bucket: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the tombstone key to the payments bucket.
|
||||||
|
err := payments.Put(paymentsBucketTombstone, []byte("1"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set tombstone: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, func() {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPaymentsBucketTombstone checks if the tombstone key exists in the payments
|
||||||
|
// bucket. It returns true if the tombstone is present and false otherwise.
|
||||||
|
func GetPaymentsBucketTombstone(db kvdb.Backend) (bool, error) {
|
||||||
|
var tombstoneExists bool
|
||||||
|
|
||||||
|
err := kvdb.View(db, func(tx kvdb.RTx) error {
|
||||||
|
// Access the top-level payments bucket.
|
||||||
|
payments := tx.ReadBucket(paymentsRootBucket)
|
||||||
|
if payments == nil {
|
||||||
|
tombstoneExists = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the tombstone key exists.
|
||||||
|
tombstone := payments.Get(paymentsBucketTombstone)
|
||||||
|
tombstoneExists = tombstone != nil
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, func() {})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tombstoneExists, nil
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package paymentsdb
|
|||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btclog/v2"
|
"github.com/btcsuite/btclog/v2"
|
||||||
"github.com/lightningnetwork/lnd/build"
|
"github.com/lightningnetwork/lnd/build"
|
||||||
|
paymentsmig1 "github.com/lightningnetwork/lnd/payments/db/migration1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// log is a logger that is initialized with no output filters. This
|
// log is a logger that is initialized with no output filters. This
|
||||||
@@ -29,4 +30,5 @@ func DisableLog() {
|
|||||||
// using btclog.
|
// using btclog.
|
||||||
func UseLogger(logger btclog.Logger) {
|
func UseLogger(logger btclog.Logger) {
|
||||||
log = logger
|
log = logger
|
||||||
|
paymentsmig1.UseLogger(logger)
|
||||||
}
|
}
|
||||||
@@ -8,4 +8,18 @@ var migrationAdditions = []MigrationConfig{
|
|||||||
Version: 12,
|
Version: 12,
|
||||||
SchemaVersion: 10,
|
SchemaVersion: 10,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "000011_payment_duplicates",
|
||||||
|
Version: 13,
|
||||||
|
SchemaVersion: 11,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "kv_payments_migration",
|
||||||
|
Version: 14,
|
||||||
|
SchemaVersion: 11,
|
||||||
|
// A migration function may be attached to this
|
||||||
|
// migration to migrate KV payments to the native SQL
|
||||||
|
// schema. This is optional and can be disabled by the
|
||||||
|
// user if necessary.
|
||||||
|
},
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user