Skip to content

Add SQLite KVStore implementation #2473

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

tnull
Copy link
Contributor

@tnull tnull commented Aug 4, 2023

Based on #2472.

We add an SQLite based implementation for the newly upstreamed KVStore interface.

@tnull
Copy link
Contributor Author

tnull commented Aug 4, 2023

Unfortunately rusqlite currently doesn't meet our MSRV, will have to figure out how to deal with that.

@tnull tnull force-pushed the 2023-08-add-sqlite-store branch 2 times, most recently from f623b6b to 58f92d9 Compare August 4, 2023 09:52
@codecov-commenter
Copy link

codecov-commenter commented Aug 4, 2023

Codecov Report

Attention: 246 lines in your changes are missing coverage. Please review.

Comparison is base (6016101) 89.03% compared to head (b67b16d) 88.80%.

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2473      +/-   ##
==========================================
- Coverage   89.03%   88.80%   -0.23%     
==========================================
  Files         112      114       +2     
  Lines       86351    86830     +479     
  Branches    86351    86830     +479     
==========================================
+ Hits        76879    77112     +233     
- Misses       7235     7444     +209     
- Partials     2237     2274      +37     
Files Coverage Δ
lightning-persister/src/sqlite_store/migrations.rs 71.85% <71.85%> (ø)
lightning-persister/src/sqlite_store/mod.rs 56.57% <56.57%> (ø)
lightning-persister/src/test_utils.rs 43.22% <6.03%> (-56.78%) ⬇️

... and 11 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@tnull tnull force-pushed the 2023-08-add-sqlite-store branch 4 times, most recently from 3def7e5 to 3e5c1f3 Compare August 4, 2023 18:25
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

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

MSRV isn't a huge deal, just need to feature-gate it and test a relevant MSRV for the feature (does rustsqlite provide some MSRV guarantees or does it just break compat at will?)

libc = "0.2"
rusqlite = { version = "0.28.0", features = ["bundled"] }
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should be optional, creating a feature for sqlite. Also, probably want no-default-features, at least.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, I think we should really discuss whether we want to make this implementation the new recommended default, in which case I'd argue we shouldn't make it optional but rather bump MSRV to have it covered.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not entirely sure what "recommended default" is - I think users can pretty easily decide if they want sqlite or filesystem storage, and we should describe in the docs when to use each.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For one I think we should support it in bindings and, at least on the Swift side, should offer the necessary glue code to make offer default implementations for the corresponding interfaces there.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmmmm, I'm not a huge fan of the dep tree here. eg fallible-streaming-iterator is one guy's personal repo with no external contributors - https://github.com/sfackler/fallible-streaming-iterator/commits/master?before=9217bc5e381b54b4ef4c38959488a5dc993b7b81+35&branch=master&qualified_name=refs%2Fheads%2Fmaster

Copy link
Collaborator

@TheBlueMatt TheBlueMatt Sep 11, 2023

Choose a reason for hiding this comment

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

Exposing our users' money to sfackler is...probably not great (but I'm sure they're a great person!)

Copy link
Collaborator

Choose a reason for hiding this comment

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

We probably can contribute upstream making those deps optional, though - they seem to see relatively little use in the library itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So generally rusqlite seems to be the most mature SQLite library out there and so far the project and code base seem pretty solid to me.

That said, I agree that reducing the dependency tree would be favorable going forward. In fact making the fallible-iterator dependency optional had been considered by rusqlite before. I now asked over at rusqlite/rusqlite#833 whether they'd be willing to accept a corresponding contribution, let's see what they say.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd say just open a pr to make both optional. No real reason to ask to ask, just do it :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, already started and made some progress. Just wanted to ask before I spend too much time going down that road :)

@TheBlueMatt
Copy link
Collaborator

Ah, looks like rusqlite doesn't have any MSRV guidelines, and is allergic to it. That's really obnoxious. I wonder if we should just link native sqlite? Its not like we need more than about two functions anyway, and we'd avoid all the dependencies of rusqlite.

@tnull tnull force-pushed the 2023-08-add-sqlite-store branch from 3e5c1f3 to 6123531 Compare August 25, 2023 12:26
@tnull
Copy link
Contributor Author

tnull commented Aug 25, 2023

Rebased on current state of #2472.

@tnull tnull force-pushed the 2023-08-add-sqlite-store branch from f020ff1 to 352ebf4 Compare August 25, 2023 13:52
@tnull tnull force-pushed the 2023-08-add-sqlite-store branch from 352ebf4 to 2417956 Compare September 7, 2023 11:05
@tnull
Copy link
Contributor Author

tnull commented Sep 7, 2023

Rebased on current state of #2472 and added the corresponding schema migrations. Currently exploring whether there is a good way to implement batch delete, or if we should just ignore the lazy tag here.

@tnull
Copy link
Contributor Author

tnull commented Sep 7, 2023

Ah, looks like rusqlite doesn't have any MSRV guidelines, and is allergic to it. That's really obnoxious. I wonder if we should just link native sqlite? Its not like we need more than about two functions anyway, and we'd avoid all the dependencies of rusqlite.

I'd rather not reimplement the world and check that it actually works on all platforms. While they don't seem to be willing to guarantee a particular MSRV, they also promised to be very conservative in that respect, and so far I can confirm that.

@tnull tnull force-pushed the 2023-08-add-sqlite-store branch 6 times, most recently from 9ea7009 to aa90767 Compare September 8, 2023 09:16
@G8XSU
Copy link
Contributor

G8XSU commented Sep 11, 2023

Is this ready for review? should we rebase?

@tnull tnull force-pushed the 2023-08-add-sqlite-store branch from aa90767 to afc7f68 Compare September 11, 2023 18:57
@tnull
Copy link
Contributor Author

tnull commented Sep 11, 2023

Is this ready for review? should we rebase?

Yes, although it probably won't make it into 0.0.117, which is why I now backported the changes here to lightningdevkit/ldk-node#151.

That said, rebased on main.

@tnull tnull force-pushed the 2023-08-add-sqlite-store branch 2 times, most recently from 69ed8b6 to a4ac95c Compare September 11, 2023 20:32
@@ -119,3 +124,112 @@ pub(crate) fn do_test_store<K: KVStore>(store_0: &K, store_1: &K) {
// Make sure everything is persisted as expected after close.
check_persisted_data!(CLOSED_CHANNEL_UPDATE_ID);
}

// A `KVStore` impl for testing purposes that wraps all our `KVStore`s and asserts their synchronicity.
pub(crate) struct TestSyncStore {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we separate this into a new PR?
I don't completely understand the need for this.
If all stores are tested independently and pass their respective unit tests, why should we have sync store ?
We should test each one of them against a set api contract/template instead of testing them against each other. (Otherwise we are implying that we are not confident with our existing api contract or tests)

Is there a specific kind of scenario we expect this test to be "catching" that won't/can't be caught using independent store unit tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can we separate this into a new PR? I don't completely understand the need for this. If all stores are tested independently and pass their respective unit tests, why should we have sync store ? We should test each one of them against a set api contract/template instead of testing them against each other. (Otherwise we are implying that we are not confident with our existing api contract or tests)

Is there a specific kind of scenario we expect this test to be "catching" that won't/can't be caught using independent store unit tests?

So, while we do and should test stores independently, we should also actually use all implementations at least for some integration tests that run actual code with actual data and assert all stores behave as expected. If we just run all tests against TestStore and test other implementations vs. synthetic test cases, we don't get a lot of test coverage of the actual usage patterns.

So, having this TestSyncStore is an easy way to use all store implementations in integration tests going forward. While we currently basically have no test cases making use of this in rust-lightning yet, there will some added with #2359, and we should definitely add more coverage going forward. We already use this in LDK Node to run most of our tests and it works great to find minor deviations and smaller stuff to keep in mind. As eventually all KVStore stuff will be upstreamed, we might as well add it as part of this PR.

We upstream our `SqliteStore` implementation that allows persistence
towards an SQLite database backend.
@tnull tnull force-pushed the 2023-08-add-sqlite-store branch from a4ac95c to 1a5dd06 Compare September 29, 2023 10:48
@tnull
Copy link
Contributor Author

tnull commented Sep 29, 2023

Rebased on current main and included latest changes from LDK Node's upgrade-to-117 PR, i.e., now accounting for the renamed namespaces.

We add a `KVStore` implementation that wraps all three of our `KVStore`
implementation and uses them in lock step while asserting they behave
identical. This will be useful for (upcoming) integration tests.
@tnull tnull force-pushed the 2023-08-add-sqlite-store branch from 1a5dd06 to b67b16d Compare September 29, 2023 10:51
@TheBlueMatt
Copy link
Collaborator

I guess this is blocked on #2473 (comment)? Are we gonna contribute upstream to making the various dependencies optional?

@tnull
Copy link
Contributor Author

tnull commented Oct 15, 2023

I guess this is blocked on #2473 (comment)?

While I agree that reducing the dependency tree is nice, it would be great if we could move forward with this independently to not be blocked on the change landing and a new version being released, etc.

Are we gonna contribute upstream to making the various dependencies optional?

Yes, hoping to get to it soon, already started as mentioned above. While making the fallible-iterator dependency optional should be trivial, I'm not so sure if it will be as simple (or even feasible) for fallible-streaming-iterator, as upstream a while back restructured their code in a few places around that. We'll see.

@TheBlueMatt
Copy link
Collaborator

Hmm, looking at fallible-streaming-iterator I'm not sure we should be taking anything that depends on it - its a solo single-dev project with relatively limited outside contribution (ie few people who are paying attention to what happens in it) - https://github.com/sfackler/fallible-streaming-iterator/commits/master. At least fallible-iterator has two folks merging it and some outside contribution - https://github.com/sfackler/rust-fallible-iterator/commits/master Sadly, hashlink is also a solo project, though it does have some outside contribution - https://github.com/kyren/hashlink/commits/master

The alternative, as much as it sucks, would be to use libsqlite3-sys directly.

@tnull
Copy link
Contributor Author

tnull commented Oct 16, 2023

Hmm, looking at fallible-streaming-iterator I'm not sure we should be taking anything that depends on it - its a solo single-dev project with relatively limited outside contribution (ie few people who are paying attention to what happens in it) - https://github.com/sfackler/fallible-streaming-iterator/commits/master. At least fallible-iterator has two folks merging it and some outside contribution - https://github.com/sfackler/rust-fallible-iterator/commits/master Sadly, hashlink is also a solo project, though it does have some outside contribution - https://github.com/kyren/hashlink/commits/master

Alright, will look into it further and find a solution. Just double-checked the rusqlite maintainers would be up for making it optional, now only have to figure out a reasonable way to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants