-
Notifications
You must be signed in to change notification settings - Fork 404
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
base: main
Are you sure you want to change the base?
Conversation
Unfortunately |
f623b6b
to
58f92d9
Compare
Codecov ReportAttention:
❗ 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
☔ View full report in Codecov by Sentry. |
3def7e5
to
3e5c1f3
Compare
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.
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?)
lightning-storage/Cargo.toml
Outdated
libc = "0.2" | ||
rusqlite = { version = "0.28.0", features = ["bundled"] } |
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.
This should be optional, creating a feature for sqlite. Also, probably want no-default-features
, at least.
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.
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.
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'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.
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.
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.
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.
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
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.
Exposing our users' money to sfackler
is...probably not great (but I'm sure they're a great person!)
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.
We probably can contribute upstream making those deps optional, though - they seem to see relatively little use in the library itself?
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.
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.
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'd say just open a pr to make both optional. No real reason to ask to ask, just do it :)
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.
Yeah, already started and made some progress. Just wanted to ask before I spend too much time going down that road :)
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. |
3e5c1f3
to
6123531
Compare
Rebased on current state of #2472. |
f020ff1
to
352ebf4
Compare
352ebf4
to
2417956
Compare
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 |
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. |
9ea7009
to
aa90767
Compare
Is this ready for review? should we rebase? |
aa90767
to
afc7f68
Compare
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. |
69ed8b6
to
a4ac95c
Compare
@@ -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 { |
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.
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?
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.
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.
a4ac95c
to
1a5dd06
Compare
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.
1a5dd06
to
b67b16d
Compare
I guess this is blocked on #2473 (comment)? Are we gonna contribute upstream to making the various dependencies optional? |
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.
Yes, hoping to get to it soon, already started as mentioned above. While making the |
Hmm, looking at The alternative, as much as it sucks, would be to use |
Alright, will look into it further and find a solution. Just double-checked the |
Based on #2472.
We add an
SQLite
based implementation for the newly upstreamedKVStore
interface.