diff --git a/src/builder.rs b/src/builder.rs index 29759e93a..ff7626ae2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -212,6 +212,8 @@ pub enum BuildError { /// /// [`KVStore`]: lightning::util::persist::KVStore KVStoreSetupFailed, + /// The configured [`KVStore`] is already in use by another node. + KVStoreAlreadyInUse, /// We failed to setup the onchain wallet. WalletSetupFailed, /// We failed to setup the logger. @@ -254,6 +256,7 @@ impl fmt::Display for BuildError { Self::WriteFailed => write!(f, "Failed to write to store."), Self::StoragePathAccessFailed => write!(f, "Failed to access the given storage path."), Self::KVStoreSetupFailed => write!(f, "Failed to setup KVStore."), + Self::KVStoreAlreadyInUse => write!(f, "KVStore is already in use by another node."), Self::WalletSetupFailed => write!(f, "Failed to setup onchain wallet."), Self::LoggerSetupFailed => write!(f, "Failed to setup the logger."), Self::ChainSourceSetupFailed => write!(f, "Failed to setup the chain source."), @@ -735,6 +738,9 @@ impl NodeBuilder { /// The given `kv_table_name` will be used or default to /// [`DEFAULT_KV_TABLE_NAME`](io::postgres_store::DEFAULT_KV_TABLE_NAME). /// + /// Returns [`BuildError::KVStoreAlreadyInUse`] while another store holds the lease. Callers may + /// retry building after a delay. + /// /// # Warning /// /// This acquires an exclusive lease for the selected KV table before reading persisted node @@ -765,6 +771,9 @@ impl NodeBuilder { Some(Arc::clone(&logger)), )) .map_err(|e| { + if e.kind() == lightning::io::ErrorKind::AlreadyExists { + return BuildError::KVStoreAlreadyInUse; + } log_error!(logger, "Failed to set up Postgres store: {e}"); BuildError::KVStoreSetupFailed })?; @@ -1332,6 +1341,9 @@ impl Builder { /// The given `kv_table_name` will be used or default to /// [`DEFAULT_KV_TABLE_NAME`](io::postgres_store::DEFAULT_KV_TABLE_NAME). /// + /// Returns [`BuildError::KVStoreAlreadyInUse`] while another store holds the lease. Callers may + /// retry building after a delay. + /// /// # Warning /// /// This acquires an exclusive lease for the selected KV table before reading persisted node diff --git a/tests/integration_tests_postgres.rs b/tests/integration_tests_postgres.rs index 280c11de5..89975de6b 100644 --- a/tests/integration_tests_postgres.rs +++ b/tests/integration_tests_postgres.rs @@ -10,7 +10,7 @@ mod common; use common::{configure_chain_source, drop_table, random_chain_source, test_connection_string}; -use ldk_node::Builder; +use ldk_node::{BuildError, Builder}; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn channel_full_cycle_with_postgres_store() { @@ -32,6 +32,14 @@ async fn channel_full_cycle_with_postgres_store() { None, ) .unwrap(); + let result = builder_a.build_with_postgres_store( + config_a.node_entropy.into(), + test_connection_string(), + None, + Some("channel_cycle_a".to_string()), + None, + ); + assert!(matches!(result, Err(BuildError::KVStoreAlreadyInUse))); node_a.start().unwrap(); println!("\n== Node B ==");