mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-06-24 15:52:22 +02:00
lnd: run invoice migration on startup
This commit runs the invoice migration if the user has a KV SQL backend configured.
This commit is contained in:
parent
94e2724a34
commit
8d20e2a23b
@ -51,6 +51,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/rpcperms"
|
||||
"github.com/lightningnetwork/lnd/signal"
|
||||
"github.com/lightningnetwork/lnd/sqldb"
|
||||
"github.com/lightningnetwork/lnd/sqldb/sqlc"
|
||||
"github.com/lightningnetwork/lnd/sweep"
|
||||
"github.com/lightningnetwork/lnd/walletunlocker"
|
||||
"github.com/lightningnetwork/lnd/watchtower"
|
||||
@ -60,6 +61,16 @@ import (
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
)
|
||||
|
||||
const (
|
||||
// invoiceMigrationBatchSize is the number of invoices that will be
|
||||
// migrated in a single batch.
|
||||
invoiceMigrationBatchSize = 1000
|
||||
|
||||
// invoiceMigration is the version of the migration that will be used to
|
||||
// migrate invoices from the kvdb to the sql database.
|
||||
invoiceMigration = 7
|
||||
)
|
||||
|
||||
// GrpcRegistrar is an interface that must be satisfied by an external subserver
|
||||
// that wants to be able to register its own gRPC server onto lnd's main
|
||||
// grpc.Server instance.
|
||||
@ -1038,7 +1049,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
if err != nil {
|
||||
cleanUp()
|
||||
|
||||
err := fmt.Errorf("unable to open graph DB: %w", err)
|
||||
err = fmt.Errorf("unable to open graph DB: %w", err)
|
||||
d.logger.Error(err)
|
||||
|
||||
return nil, nil, err
|
||||
@ -1072,65 +1083,69 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
case err != nil:
|
||||
cleanUp()
|
||||
|
||||
err := fmt.Errorf("unable to open graph DB: %w", err)
|
||||
err = fmt.Errorf("unable to open graph DB: %w", err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Instantiate a native SQL invoice store if the flag is set.
|
||||
// Instantiate a native SQL store if the flag is set.
|
||||
if d.cfg.DB.UseNativeSQL {
|
||||
migrations := sqldb.GetMigrations()
|
||||
|
||||
// If the user has not explicitly disabled the SQL invoice
|
||||
// migration, attach the custom migration function to invoice
|
||||
// migration (version 7). Even if this custom migration is
|
||||
// disabled, the regular native SQL store migrations will still
|
||||
// run. If the database version is already above this custom
|
||||
// migration's version (7), it will be skipped permanently,
|
||||
// regardless of the flag.
|
||||
if !d.cfg.DB.SkipSQLInvoiceMigration {
|
||||
migrationFn := func(tx *sqlc.Queries) error {
|
||||
return invoices.MigrateInvoicesToSQL(
|
||||
ctx, dbs.ChanStateDB.Backend,
|
||||
dbs.ChanStateDB, tx,
|
||||
invoiceMigrationBatchSize,
|
||||
)
|
||||
}
|
||||
|
||||
// Make sure we attach the custom migration function to
|
||||
// the correct migration version.
|
||||
for i := 0; i < len(migrations); i++ {
|
||||
if migrations[i].Version != invoiceMigration {
|
||||
continue
|
||||
}
|
||||
|
||||
migrations[i].MigrationFn = migrationFn
|
||||
}
|
||||
}
|
||||
|
||||
// We need to apply all migrations to the native SQL store
|
||||
// before we can use it.
|
||||
err := dbs.NativeSQLStore.ApplyAllMigrations(
|
||||
ctx, sqldb.GetMigrations(),
|
||||
)
|
||||
err = dbs.NativeSQLStore.ApplyAllMigrations(ctx, migrations)
|
||||
if err != nil {
|
||||
cleanUp()
|
||||
err := fmt.Errorf("unable to apply migrations: %w", err)
|
||||
d.logger.Error(err)
|
||||
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// KV invoice db resides in the same database as the channel
|
||||
// state DB. Let's query the database to see if we have any
|
||||
// invoices there. If we do, we won't allow the user to start
|
||||
// lnd with native SQL enabled, as we don't currently migrate
|
||||
// the invoices to the new database schema.
|
||||
invoiceSlice, err := dbs.ChanStateDB.QueryInvoices(
|
||||
ctx, invoices.InvoiceQuery{
|
||||
NumMaxInvoices: 1,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
cleanUp()
|
||||
d.logger.Errorf("Unable to query KV invoice DB: %v",
|
||||
err)
|
||||
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if len(invoiceSlice.Invoices) > 0 {
|
||||
cleanUp()
|
||||
err := fmt.Errorf("found invoices in the KV invoice " +
|
||||
"DB, migration to native SQL is not yet " +
|
||||
"supported")
|
||||
err = fmt.Errorf("faild to run migrations for the "+
|
||||
"native SQL store: %w", err)
|
||||
d.logger.Error(err)
|
||||
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// With the DB ready and migrations applied, we can now create
|
||||
// the base DB and transaction executor for the native SQL
|
||||
// invoice store.
|
||||
baseDB := dbs.NativeSQLStore.GetBaseDB()
|
||||
executor := sqldb.NewTransactionExecutor(
|
||||
baseDB,
|
||||
func(tx *sql.Tx) invoices.SQLInvoiceQueries {
|
||||
baseDB, func(tx *sql.Tx) invoices.SQLInvoiceQueries {
|
||||
return baseDB.WithTx(tx)
|
||||
},
|
||||
)
|
||||
|
||||
dbs.InvoiceDB = invoices.NewSQLStore(
|
||||
sqlInvoiceDB := invoices.NewSQLStore(
|
||||
executor, clock.NewDefaultClock(),
|
||||
)
|
||||
|
||||
dbs.InvoiceDB = sqlInvoiceDB
|
||||
} else {
|
||||
dbs.InvoiceDB = dbs.ChanStateDB
|
||||
}
|
||||
@ -1143,7 +1158,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
if err != nil {
|
||||
cleanUp()
|
||||
|
||||
err := fmt.Errorf("unable to open %s database: %w",
|
||||
err = fmt.Errorf("unable to open %s database: %w",
|
||||
lncfg.NSTowerClientDB, err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
@ -1158,7 +1173,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
||||
if err != nil {
|
||||
cleanUp()
|
||||
|
||||
err := fmt.Errorf("unable to open %s database: %w",
|
||||
err = fmt.Errorf("unable to open %s database: %w",
|
||||
lncfg.NSTowerServerDB, err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
|
BIN
invoices/testdata/channel.db
vendored
BIN
invoices/testdata/channel.db
vendored
Binary file not shown.
@ -87,6 +87,8 @@ type DB struct {
|
||||
|
||||
UseNativeSQL bool `long:"use-native-sql" description:"Use native SQL for tables that already support it."`
|
||||
|
||||
SkipSQLInvoiceMigration bool `long:"skip-sql-invoice-migration" description:"Do not migrate invoices stored in our key-value database to native SQL."`
|
||||
|
||||
NoGraphCache bool `long:"no-graph-cache" description:"Don't use the in-memory graph cache for path finding. Much slower but uses less RAM. Can only be used with a bolt database backend."`
|
||||
|
||||
PruneRevocation bool `long:"prune-revocation" description:"Run the optional migration that prunes the revocation logs to save disk space."`
|
||||
@ -115,7 +117,8 @@ func DefaultDB() *DB {
|
||||
MaxConnections: defaultSqliteMaxConnections,
|
||||
BusyTimeout: defaultSqliteBusyTimeout,
|
||||
},
|
||||
UseNativeSQL: false,
|
||||
UseNativeSQL: false,
|
||||
SkipSQLInvoiceMigration: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1472,6 +1472,9 @@
|
||||
; own risk.
|
||||
; db.use-native-sql=false
|
||||
|
||||
; If set to true, native SQL invoice migration will be skipped. Note that this
|
||||
; option is intended for users who experience non-resolvable migration errors.
|
||||
; db.skip-sql-invoice-migration=false
|
||||
|
||||
[etcd]
|
||||
|
||||
|
@ -61,6 +61,15 @@ var (
|
||||
Version: 6,
|
||||
SchemaVersion: 6,
|
||||
},
|
||||
{
|
||||
Name: "kv_invoice_migration",
|
||||
Version: 7,
|
||||
SchemaVersion: 6,
|
||||
// A migration function is may be attached to this
|
||||
// migration to migrate KV invoices to the native SQL
|
||||
// schema. This is optional and can be disabled by the
|
||||
// user if necessary.
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user