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/msgmux"
|
||||
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/signal"
|
||||
"github.com/lightningnetwork/lnd/sqldb"
|
||||
@@ -76,6 +78,10 @@ const (
|
||||
// graphMigration is the version number for the graph migration
|
||||
// that migrates the KV graph to the native SQL schema.
|
||||
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
|
||||
@@ -1153,6 +1159,31 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
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
|
||||
// the correct migration version.
|
||||
for i := 0; i < len(migrations); i++ {
|
||||
@@ -1162,11 +1193,17 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
migrations[i].MigrationFn = invoiceMig
|
||||
|
||||
continue
|
||||
|
||||
case graphMigration:
|
||||
migrations[i].MigrationFn = graphMig
|
||||
|
||||
continue
|
||||
|
||||
case paymentMigration:
|
||||
migrations[i].MigrationFn = paymentMig
|
||||
|
||||
continue
|
||||
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -1265,6 +1302,27 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
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
|
||||
|
||||
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 (
|
||||
"github.com/btcsuite/btclog/v2"
|
||||
"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
|
||||
@@ -29,4 +30,5 @@ func DisableLog() {
|
||||
// using btclog.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
paymentsmig1.UseLogger(logger)
|
||||
}
|
||||
@@ -8,4 +8,18 @@ var migrationAdditions = []MigrationConfig{
|
||||
Version: 12,
|
||||
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