-
Notifications
You must be signed in to change notification settings - Fork 102
Add SqliteStore
backend
#100
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
Conversation
603a52f
to
5cf438d
Compare
Can we move the last commit of SQLite impl in separate PR, would like to review it separately. :) |
Mh, I'd actually rather not have yet another PR to maintain and rebase. But whatever. Now moved the first 3 commits to #101 upon which this PR is now based. |
KVStore
configurable and add SqliteStore
backendSqliteStore
backend
309881f
to
ce7819a
Compare
Rebased on current #101 and added a corresponding fixup that avoids allocating |
src/io/sqlite_store.rs
Outdated
|
||
impl KVStorePersister for SqliteStore { | ||
fn persist<W: Writeable>(&self, prefixed_key: &str, object: &W) -> lightning::io::Result<()> { | ||
let msg = format!("Could not persist file for key {}.", prefixed_key); |
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.
since this is not a filesystem store, we don't need or shouldn't use parent dir as namespace,
instead we could use a static string as namespace like "ldk_core_store"?
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.
since this is not a filesystem store, we don't need or shouldn't use parent dir as namespace, instead we could use a static string as namespace like "ldk_core_store"?
Yes we should, as unfortunately LDK persistence makes strong assumptions about the structure of the keys and for example gives us channel monitors as keys monitors/[txid][index]
. Plus, having the different backends decide to rename namespaces is a bad idea when it comes to migration between backends. I now DRYed up the key splitting however.
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.
"having the different backends decide to rename namespaces is a bad idea". yes exactly
that is why we should not be using anything to do with parent directories and key parsing from ldk-key as namespace keys. (for all kvstores including filesystem)
afaiu, ldk doesn't enforce anything by having keys like "monitors/[txid][index]", ldk is just providing a prefix.
we could have something like "ldk_core" as namespace and "monitors/[txid][index]" as full key.
otherwise we are letting ldk-core create namespaces dynamically instead of ldk-node having fixed set of namespaces.(even though we own ldk-core, this is not ideal from ldk-node user perspective)
otherwise, in future, if ldk decides to store something new as "xyzMeta/" we would end up creating a namespace out of it and migration code will need to change.
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.
"having the different backends decide to rename namespaces is a bad idea". yes exactly that is why we should not be using anything to do with parent directories and key parsing from ldk-key as namespace keys. (for all kvstores including filesystem)
afaiu, ldk doesn't enforce anything by having keys like "monitors/[txid][index]", ldk is just providing a prefix. we could have something like "ldk_core" as namespace and "monitors/[txid][index]" as full key.
No, it's clearly not just a prefix but an implied namespace, actually even an implied path as all assumptions are made around FilesystemPersister
. We should def. not buy into the hardcoded prefixes but rather extract them and use them in a sane way. This is exactly why I added the namespaces to the KVStore
interface in the first place, and I'll be looking into upstreaming them, as the hardcoded strings cluttered over different places in the code is just a mess. I'll def. won't throw "everything LDK" into a single namespace.
otherwise we are letting ldk-core create namespaces dynamically instead of ldk-node having fixed set of namespaces.(even though we own ldk-core, this is not ideal from ldk-node user perspective)
We have a pretty good grasp on what's going on in the upstream codebase and we don't make any promises about what namespaces exactly the user needs to handle: the interface takes a namespace: &str
instead of an enum
for a reason. So yes, any implementation of the KVStore
should be able to handle new namespaces without issue.
otherwise, in future, if ldk decides to store something new as "xyzMeta/" we would end up creating a namespace out of it and migration code will need to change.
Yes, this was why I thought about adding a list_namespaces
method to the interface to make all data explorable by way of the interface. However, I still think we made the right decision to keep migration out-of-bound.
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.
No, it's clearly not just a prefix but an implied namespace, actually even an implied path as all assumptions are made around FilesystemPersister
there is no enforced implied namespace, cash-lit doesn't care about it, ldk doesn't care about it. We are making that assumption right now in this PR, as we split the key into a file-path for a non-filesystem-directory datastore. We shouldn't be thinking of this having any relation to file-path or filesystem-directory/subdirectory.
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.
there is no enforced implied namespace, cash-lit doesn't care about it, ldk doesn't care about it. We are making that assumption right now in this PR, as we split the key into a file-path for a non-filesystem-directory datastore. We shouldn't be thinking of this having any relation to file-path or filesystem-directory/subdirectory.
Alright, I assume you'd then argue to do the same in FilesystemStore
, i.e., save all LDK objects in a single directory? The prefix is exactly why I added namespaces in the first place, and I'll be using them in this PR for this KVStore
unless there is a convincing technical argument not to. Even though I don't think it matters all too much, please note it would also be less performant to always retrieve all rows from the entire LDK namespace and filter them down to the keys we want, e.g., in read_channelmonitors
.
I'm sorry but this simply doesn't make sense. If VSS doesn't support namespaces that's fine, then you should find a workaround in the respectiveKVStore
impl and that may be to keep the keys prefixed, but maybe there is a better way to do it also.
9521a41
to
5bf9d57
Compare
Rebased on main after merging #101 and addressed the feedback so far. |
22b8760
to
121b96c
Compare
52856b7
to
6eb6375
Compare
Rebased on main after #88 landed. |
6eb6375
to
d66bb1a
Compare
Squashed without further changes. |
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.
Overall LGTM
d66bb1a
to
a53f74a
Compare
Amended last commit to include the following change: diff --git a/src/io/sqlite_store.rs b/src/io/sqlite_store.rs
index 6d7e166..ee38f5d 100644
--- a/src/io/sqlite_store.rs
+++ b/src/io/sqlite_store.rs
@@ -118,9 +118,8 @@ impl KVStore for SqliteStore {
fn remove(&self, namespace: &str, key: &str) -> std::io::Result<bool> {
+ let locked_conn = self.connection.lock().unwrap();
+
let sql = format!("DELETE FROM {} WHERE namespace=:namespace AND key=:key;", KV_TABLE_NAME);
- let changes = self
- .connection
- .lock()
- .unwrap()
+ let changes = locked_conn
.execute(
&sql, |
We here add an `KVStore` implementation on SQLite, which becomes the new default for `Node::build`. The `FilesystemStore` is still configurable via `Node::build_with_fs_store`
a53f74a
to
4653e5c
Compare
Rebased on main after #108 was merged. |
What's the reasoning behind having KV storage instead of a full SQL schema? |
Well, for one LDK's 'native' serialization format is TLV-encoded blobs that are persisted under particular keys. BDK will follow a similar approach with the upcoming changes in 1.0. So it didn't really make sense to follow an entirely different model for LDK Node's own objects. Additionally, I'm not sure a 'real' SQL schema would have much benefits over the key value approach and the latter also allows a much simpler |
Based on #101.Finally, we add an SQLite-based
KVStore
implementation which becomes the new defaultdefault for
Node::build
. TheFilesystemStore
is still configurable viaNode::build_with_fs_store