Skip to content
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

Migrate from boltdb to sql #585

Merged
merged 16 commits into from
Jun 20, 2023
Merged

Migrate from boltdb to sql #585

merged 16 commits into from
Jun 20, 2023

Conversation

sputn1ck
Copy link
Member

@sputn1ck sputn1ck commented May 17, 2023

This PR adds the migration from boltdb to a local sqlite db or a postgres db. This will make it easier for future improvements such as taproots assets and other protocol changes.

Currently the migration is only done once from boltdb to the specified sql store. We should add a migrate command to loop which will allow the migration from sqlite to postgres and back.

TODO

  • cleanup commits
  • better comments
  • write migration from boltdb to sqlite
  • use sqlite as base db
  • update release notes

@sputn1ck sputn1ck force-pushed the sqlite branch 5 times, most recently from 0322c84 to 0c26796 Compare May 19, 2023 13:11
@sputn1ck sputn1ck marked this pull request as ready for review May 19, 2023 13:12
@sputn1ck sputn1ck force-pushed the sqlite branch 7 times, most recently from 79160c1 to 1bb62b7 Compare May 19, 2023 13:42
@sputn1ck sputn1ck force-pushed the sqlite branch 2 times, most recently from 0247b6e to cfc3c0c Compare May 23, 2023 16:53
Copy link
Member

@GeorgeTsagk GeorgeTsagk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cACK, not super expert in db migrations

will do another review run soon so I can also provide a tACK

@@ -192,13 +192,13 @@ func NewClient(dbDir string, cfg *ClientConfig) (*Client, func(), error) {
}

// FetchSwaps returns all loop in and out swaps currently in the database.
func (s *Client) FetchSwaps() ([]*SwapInfo, error) {
loopOutSwaps, err := s.Store.FetchLoopOutSwaps()
func (s *Client) FetchSwaps(ctx context.Context) ([]*SwapInfo, error) {
Copy link
Member

@GeorgeTsagk GeorgeTsagk May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird that we didn't have a ctx before. Isn't it like a rule-of-thumb to have a context with timeout when dispatching db calls?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for adding timeout, perhaps something large like 30s would be a good start.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bhandras do you mean on every call to add a timeout to the context?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is that we could perhaps wrap the ctx to a timeout context (per call to the store), to avoid hanging if the DB is for any reason unresponsive.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, but think the sql driver handles that? There are some timeout settings we pass in sqlite for example


// If the migration was successfull we'll rename the bolt db to
// loop.db.bk.
err = os.Rename(
Copy link
Member

@GeorgeTsagk GeorgeTsagk May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is keeping the backup what usually happens with migrations?

what if db was super big and keeping a duplicate causes problems?
(e.g a user with many swaps)
is the following a possible scenario:

  • user upgrades & triggers migration
  • migration completes but now they suddenly reached 99% storage capacity
  • service outage

or what if migration fails without completing, possibly exhausting all of storage space?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. My rationale is to have a backup in case something goes wrong. IMO that's important for client side migration. Users can then delete their database on their own.

Should the user run out of space the migration would fail on the migration step before and loopd wouldn't start and the db wouldn't rename, so a user could expand their db. There would be no fallback just an exit from loopd.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @sputn1ck, it's important to keep the old DB around. It's also likely not large enough to cause any issues regarding storage space and if it is, then the migration above will already fail since this is just a rename.

loopd/migration.go Show resolved Hide resolved
loopdb/sqlite/queries/swaps.sql Outdated Show resolved Hide resolved
loopdb/sqlite/queries/swaps.sql Outdated Show resolved Hide resolved
loopdb/sqlite/queries/swaps.sql Outdated Show resolved Hide resolved
sqlc.yaml Outdated Show resolved Hide resolved
loopdb/sqlite/queries/liquidity_params.sql Outdated Show resolved Hide resolved

// For each loop out, create a new loop out in the toStore.
for _, loopOut := range loopOuts {
err := m.toStore.CreateLoopOut(ctx, loopOut.Hash, loopOut.Contract)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to speed this up, we want to be able to batch all the insertion here. Otherwise, you're doing a single db transaction for each swap. Instead a series of swaps can be created, within a single DB transaction.

@sputn1ck sputn1ck changed the title Migrate from boltdb to sqlite Migrate from boltdb to sql May 30, 2023
@sputn1ck sputn1ck force-pushed the sqlite branch 6 times, most recently from fe55f1c to 148e9e4 Compare May 30, 2023 09:19
Copy link
Member

@bhandras bhandras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! First pass looks really good already! Very close 🚀

@@ -28,10 +31,11 @@ require (
github.com/stretchr/testify v1.8.1
github.com/urfave/cli v1.22.9
golang.org/x/net v0.7.0
google.golang.org/grpc v1.41.0
google.golang.org/grpc v1.45.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bump is because of golang-migrate?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually not sure where the bump comes from.

loopdb/macaroons.go Outdated Show resolved Hide resolved
client.go Outdated Show resolved Hide resolved
@@ -192,13 +192,13 @@ func NewClient(dbDir string, cfg *ClientConfig) (*Client, func(), error) {
}

// FetchSwaps returns all loop in and out swaps currently in the database.
func (s *Client) FetchSwaps() ([]*SwapInfo, error) {
loopOutSwaps, err := s.Store.FetchLoopOutSwaps()
func (s *Client) FetchSwaps(ctx context.Context) ([]*SwapInfo, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for adding timeout, perhaps something large like 30s would be a good start.

loopdb/interface.go Outdated Show resolved Hide resolved
loopdb/sqlite_store.go Outdated Show resolved Hide resolved
loopdb/sqlite_store.go Outdated Show resolved Hide resolved
loopdb/sqlite_store.go Outdated Show resolved Hide resolved
loopdb/sqlite_store.go Outdated Show resolved Hide resolved
loopdb/postgres.go Outdated Show resolved Hide resolved
@lightninglabs-deploy
Copy link

@sputn1ck, remember to re-request review from reviewers when ready

This commit adds a context to our loopdb interface, which we should use
in the sqlite migration.
This commit adds a batch insert to the interface. This greatly reduces
the time the migration will take. It is not implemented for the boltdb, as
we will not be supporting migrating to the boltdb.
Copy link
Member

@bhandras bhandras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK, LGTM! Excellent work @sputn1ck 🎉 🎉 🎉

Please don't forget to update the release notes as well.

loopdb/sql_store.go Outdated Show resolved Hide resolved
loopdb/sql_store.go Outdated Show resolved Hide resolved
loopdb/sql_store.go Outdated Show resolved Hide resolved
loopdb/sql_store.go Outdated Show resolved Hide resolved
loopdb/sql_store.go Show resolved Hide resolved
loopdb/sql_test.go Show resolved Hide resolved
loopd/migration.go Outdated Show resolved Hide resolved
loopd/migration.go Outdated Show resolved Hide resolved
)

// migrateBoltdb migrates the boltdb to sqlite.
func migrateBoltdb(ctx context.Context, cfg *Config) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps as a separate PR we can also add the option to migrate sqlite to postgres. Not needed now since there're no users yet on sqlite.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I thought about that as well, shouldn't be too much extra work

This commit adds a nil check to the boltdb liquidity test. There was
a difference between the sqlite and boltdb implementation. This test
covers that.
This commit adds a postgres store to the loopdb package.
Ths postgres migrator uses a replacer filesystem to replace the
sqlite types to postgres types in the migration.
This commit adds a migrator to the loopdb package that manages migrating
between 2 databases
This commit adds the ability to choose between different sql stores
for loopd. The default is sqlite, but it can be changed to postgres.
@sputn1ck sputn1ck merged commit 0781caf into lightninglabs:master Jun 20, 2023
@sputn1ck sputn1ck deleted the sqlite branch June 20, 2023 17:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants