Conversation
|
👋 Thanks for assigning @tnull as a reviewer! |
tnull
left a comment
There was a problem hiding this comment.
Took a first high-level look.
Also gates sqlite behind a feature flag, since most tests relied on this, we ended up needing to gate a lot of them behind the flag. Curious on thoughts on how to handle this best
Not sure I'm following? Why do we want to feature-gate tests based on SQLite?
Also tagging @tankyleo as a secondary reviewer here as he has a lot of recent experience with Postgres on VSS Server.
|
|
||
| // An internal runtime we use to avoid any deadlocks we could hit when waiting on async | ||
| // operations to finish from a sync context. | ||
| internal_runtime: Option<tokio::runtime::Runtime>, |
There was a problem hiding this comment.
I think we could avoid using an internal runtime for this and rather just reuse crate::runtime::Runtime, if we wanted. Though, when upstreaming to LDK we'll need to rethink all of this anyways (cf. VssStore upstreaming PR).
There was a problem hiding this comment.
Yeah I just copied VSS to be safe.
There was a problem hiding this comment.
Yeah, let's drop the extra runtime then.
|
|
||
| /// Builds a [`Node`] instance with a [`SqliteStore`] backend and according to the options | ||
| /// previously configured. | ||
| #[cfg(feature = "sqlite")] |
There was a problem hiding this comment.
Why do we suddenly introduce features? We so far held off and meant to do that in a dedicated PR at some point for this or next release. Is it necessary to make Postgres work?
There was a problem hiding this comment.
okay removed for now
There was a problem hiding this comment.
Seems the postgres feature is still present in the current version?
b5d297e to
e8f478b
Compare
|
Did fixes in follow up commits for ease of review. |
|
🔔 1st Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @tankyleo! This PR has been waiting for your review. |
tankyleo
left a comment
There was a problem hiding this comment.
Verbose review, please dismiss aggressively :)
|
@tankyleo addressed most of your comments. Lots of docs improvements. Better handling around the db name and creating the db. And did the code clean ups + test improvements you suggested. |
a8589ea to
a43b13b
Compare
|
🔔 1st Reminder Hey @tankyleo! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @tankyleo! This PR has been waiting for your review. |
3bb9810 to
437f11f
Compare
tankyleo
left a comment
There was a problem hiding this comment.
two small nits thank you
Add a PostgresStore implementation behind the "postgres" feature flag, mirroring the existing SqliteStore. Uses tokio-postgres (async-native) with an internal tokio runtime for the sync KVStoreSync trait, following the VssStore pattern. Includes unit tests, integration tests (channel full cycle and node restart), and a CI workflow that runs both against a PostgreSQL service container. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fixed |
|
🔔 1st Reminder Hey @tnull! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @tnull! This PR has been waiting for your review. |
| } | ||
|
|
||
| // Default to sslmode=require when TLS is configured | ||
| if matches!(tls, PgTlsConnector::NativeTls(_)) && config.get_ssl_mode() == SslMode::Prefer { |
There was a problem hiding this comment.
Claude:
- Silent TLS downgrade. new() only upgrades SslMode::Prefer → Require when tls_config is Some. If a caller passes tls_config=Some(...) but a connection string with sslmode=disable, the connection is plaintext despite having opted into TLS. Consider erroring (or forcing Require) when
tls_config.is_some() and sslmode is Disable/Allow. src/io/postgres_store/mod.rs:385.
| ); | ||
|
|
||
| // Try connecting to the target database directly — if it exists we're done. | ||
| let initial_err = match Self::make_config_connection(config, tls).await { |
There was a problem hiding this comment.
Claude:
- Swallowed initial connect error. create_database_if_not_exists treats any connect failure to the target DB as "DB doesn't exist" (src/io/postgres_store/mod.rs:490). Auth failures, wrong port, etc. fall through to the bootstrap-connect path. The final error message does include initial_err,
which is good, but logging it at debug! before swallowing would help diagnose the common "looks like it worked, actually didn't" case.
| /// [`DEFAULT_DB_NAME`](io::postgres_store::DEFAULT_DB_NAME). The database will be created | ||
| /// automatically if it doesn't already exist. The `connection_string` must not include a | ||
| /// `dbname` when `db_name` is set, providing both is an error. When auto-creating the | ||
| /// database if is doesn't exist, the initial connection is made using the default database |
There was a problem hiding this comment.
| /// database if is doesn't exist, the initial connection is made using the default database | |
| /// database if it doesn't exist, the initial connection is made using the default database |
| check_namespace_key_validity(primary_namespace, secondary_namespace, Some(key), "read")?; | ||
|
|
||
| let mut locked_client = self.client.lock().await; | ||
| self.ensure_connected(&mut locked_client).await?; |
There was a problem hiding this comment.
Calling this on every operation should cost us an extra RTT each time, no?
| } | ||
|
|
||
| struct PostgresStoreInner { | ||
| client: tokio::sync::Mutex<Client>, |
There was a problem hiding this comment.
Rather than just using a single client, can we steal vss-server's SmallPool to not make all operations fully sync and sequenced?
| /// | ||
| /// [PostgreSQL]: https://www.postgresql.org | ||
| #[cfg(feature = "postgres")] | ||
| pub fn build_with_postgres_store( |
There was a problem hiding this comment.
We'll need to add this to ldk_node.udl to actually make this useful in bindings.
| secondary_namespace TEXT NOT NULL DEFAULT '', | ||
| key TEXT NOT NULL CHECK (key <> ''), | ||
| value BYTEA, | ||
| sort_order BIGINT NOT NULL DEFAULT 0 CHECK (sort_order >= 0), |
There was a problem hiding this comment.
Should we now also follow what we did in lightningdevkit/vss-server#96 and use BIGSERIAL?
| /// The given `db_name` will be used or default to | ||
| /// [`DEFAULT_DB_NAME`](io::postgres_store::DEFAULT_DB_NAME). The database will be created | ||
| /// automatically if it doesn't already exist. The `connection_string` must not include a | ||
| /// `dbname` when `db_name` is set, providing both is an error. When auto-creating the | ||
| /// database if it doesn't exist, the initial connection is made using the default database | ||
| /// `postgres`. |
There was a problem hiding this comment.
Small doc nit, the "initial connection is made using the default database postgres" isn't quite accurate, as the initial connection actually goes to the target database, and postgres is only used as a fallback to create it. Could we reorder this so it reads in the order the code actually runs? The same applies to the ArcedNodeBuilder doc below and PostgresStore::new in postgres_store/mod.rs. Suggested wording:
The given `db_name` will be used or default to [`DEFAULT_DB_NAME`](io::postgres_store::DEFAULT_DB_NAME). The `connection_string` must not include a `dbname` when `db_name` is set, providing both is an error. The database will be created automatically if it doesn't already exist. The initial connection is made to the target database, and if it fails we fall back to the default `postgres` database to create it.
| } | ||
|
|
||
| struct PostgresStoreInner { | ||
| client: tokio::sync::Mutex<Client>, |
There was a problem hiding this comment.
I noticed Mutex<Client> is used here. Since Postgres handles concurrent queries server-side (unlike SQLite), is this intentional for simplicity or to match SqliteStore?
Add a PostgresStore implementation behind the
postgresfeature flag, mirroring the existingSqliteStore. Usestokio-postgres(async-native) with an internal tokio runtime for the syncKVStoreSynctrait, following theVssStorepattern.Also gates sqlite behind a feature flag, since most tests relied on this, we ended up needing to gate a lot of them behind the flag. Curious on thoughts on how to handle this best