-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
invoices: migrate KV invoices to native SQL for users of KV SQL backends #8831
base: master
Are you sure you want to change the base?
Changes from all commits
14afde1
7da7450
6921238
69e0f8f
93469d7
1c74e11
3830e75
27fec74
4894c07
492c2c4
af500cc
4dbb25b
21ce4e7
2291def
e8d6558
3516c16
4c09270
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -138,7 +138,7 @@ require ( | |
github.com/opencontainers/image-spec v1.0.2 // indirect | ||
github.com/opencontainers/runc v1.1.12 // indirect | ||
github.com/ory/dockertest/v3 v3.10.0 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 | ||
github.com/prometheus/client_model v0.2.0 // indirect | ||
github.com/prometheus/common v0.26.0 // indirect | ||
github.com/prometheus/procfs v0.6.0 // indirect | ||
|
@@ -207,6 +207,10 @@ replace github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2 | |
// allows us to specify that as an option. | ||
replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display | ||
|
||
// Temporary replace until https://github.com/lightningnetwork/lnd/pull/8831 is | ||
// merged. | ||
replace github.com/lightningnetwork/lnd/sqldb => ./sqldb | ||
Comment on lines
+210
to
+212
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like this commit should be dropped. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this is still needed as we modify the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since this is close to merge - should we not split this up into 2 PRs? 1) that updates sqldb and 2) that points to that one? so that we dont merge with this replacement. or is the plan just to do an immediate follow up removing the replace? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both works imo, I'm happy to split it up once we get all approves :) |
||
|
||
// If you change this please also update docs/INSTALL.md and GO_VERSION in | ||
// Makefile (then run `make lint` to see where else it needs to be updated as | ||
// well). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package invoices_test | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"testing" | ||
"time" | ||
|
||
"github.com/lightningnetwork/lnd/channeldb" | ||
"github.com/lightningnetwork/lnd/clock" | ||
invpkg "github.com/lightningnetwork/lnd/invoices" | ||
"github.com/lightningnetwork/lnd/sqldb" | ||
"github.com/lightningnetwork/lnd/sqldb/sqlc" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// TestMigrationWithChannelDB tests the migration of invoices from a bolt backed | ||
// channel.db to a SQL database. Note that this test does not attempt to be a | ||
// complete migration test for all invoice types but rather is added as a tool | ||
// for developers and users to debug invoice migration issues with an actual | ||
// channel.db file. | ||
func TestMigrationWithChannelDB(t *testing.T) { | ||
// First create a shared Postgres instance so we don't spawn a new | ||
// docker container for each test. | ||
pgFixture := sqldb.NewTestPgFixture( | ||
t, sqldb.DefaultPostgresFixtureLifetime, | ||
) | ||
t.Cleanup(func() { | ||
pgFixture.TearDown(t) | ||
}) | ||
|
||
makeSQLDB := func(t *testing.T, sqlite bool) (*invpkg.SQLStore, | ||
*sqldb.TransactionExecutor[*sqlc.Queries]) { | ||
|
||
var db *sqldb.BaseDB | ||
if sqlite { | ||
db = sqldb.NewTestSqliteDB(t).BaseDB | ||
} else { | ||
db = sqldb.NewTestPostgresDB(t, pgFixture).BaseDB | ||
} | ||
|
||
invoiceExecutor := sqldb.NewTransactionExecutor( | ||
db, func(tx *sql.Tx) invpkg.SQLInvoiceQueries { | ||
return db.WithTx(tx) | ||
}, | ||
ellemouton marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
genericExecutor := sqldb.NewTransactionExecutor( | ||
db, func(tx *sql.Tx) *sqlc.Queries { | ||
return db.WithTx(tx) | ||
}, | ||
) | ||
|
||
testClock := clock.NewTestClock(time.Unix(1, 0)) | ||
|
||
return invpkg.NewSQLStore(invoiceExecutor, testClock), | ||
genericExecutor | ||
} | ||
|
||
migrationTest := func(t *testing.T, kvStore *channeldb.DB, | ||
sqlite bool) { | ||
|
||
sqlInvoiceStore, sqlStore := makeSQLDB(t, sqlite) | ||
ctxb := context.Background() | ||
|
||
const batchSize = 11 | ||
ellemouton marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var opts sqldb.MigrationTxOptions | ||
err := sqlStore.ExecTx( | ||
ctxb, &opts, func(tx *sqlc.Queries) error { | ||
return invpkg.MigrateInvoicesToSQL( | ||
ctxb, kvStore.Backend, kvStore, tx, | ||
batchSize, | ||
) | ||
}, func() {}, | ||
) | ||
require.NoError(t, err) | ||
|
||
// MigrateInvoices will check if the inserted invoice equals to | ||
// the migrated one, but as a sanity check, we'll also fetch the | ||
// invoices from the store and compare them to the original | ||
// invoices. | ||
query := invpkg.InvoiceQuery{ | ||
IndexOffset: 0, | ||
// As a sanity check, fetch more invoices than we have | ||
// to ensure that we did not add any extra invoices. | ||
// Note that we don't really have a way to know the | ||
// exact number of invoices in the bolt db without first | ||
// iterating over all of them, but for test purposes | ||
// constant should be enough. | ||
NumMaxInvoices: 9999, | ||
ziggie1984 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
result1, err := kvStore.QueryInvoices(ctxb, query) | ||
require.NoError(t, err) | ||
numInvoices := len(result1.Invoices) | ||
|
||
result2, err := sqlInvoiceStore.QueryInvoices(ctxb, query) | ||
require.NoError(t, err) | ||
require.Equal(t, numInvoices, len(result2.Invoices)) | ||
|
||
// Simply zero out the add index so we don't fail on that when | ||
// comparing. | ||
for i := 0; i < numInvoices; i++ { | ||
result1.Invoices[i].AddIndex = 0 | ||
result2.Invoices[i].AddIndex = 0 | ||
|
||
// We need to override the timezone of the invoices as | ||
// the provided DB vs the test runners local time zone | ||
// might be different. | ||
invpkg.OverrideInvoiceTimeZone(&result1.Invoices[i]) | ||
invpkg.OverrideInvoiceTimeZone(&result2.Invoices[i]) | ||
|
||
require.Equal( | ||
t, result1.Invoices[i], result2.Invoices[i], | ||
) | ||
} | ||
} | ||
|
||
tests := []struct { | ||
name string | ||
dbPath string | ||
}{ | ||
{ | ||
"empty", | ||
t.TempDir(), | ||
}, | ||
{ | ||
"testdata", | ||
"testdata", | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
test := test | ||
t.Run(test.name, func(t *testing.T) { | ||
store := channeldb.OpenForTesting(t, test.dbPath) | ||
|
||
t.Run("Postgres", func(t *testing.T) { | ||
migrationTest(t, store, false) | ||
}) | ||
|
||
t.Run("SQLite", func(t *testing.T) { | ||
migrationTest(t, store, true) | ||
}) | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dont we still want this check for anyone who has set
d.cfg.DB.SkipSQLInvoiceMigration=true
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and to protect against users who had a bbolt invoice store before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think it’s necessary, as this check was primarily intended to ensure that users with existing invoices in their database wouldn’t be able to start LND without the migration in place.
Since we don’t currently support mixed backends, the only scenario to consider is if the user is already using an SQL database but with the older KV schema.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yes i see: if the user was pointing to a bbolt store and then changes config to sql store, there really isnt any way for us to know this so it is essentially a new node