From 55b4174936f5556b24f304c9a0749490f2fc931a Mon Sep 17 00:00:00 2001 From: Yuki Kishimoto Date: Mon, 15 Jan 2024 18:45:03 +0100 Subject: [PATCH] sdk: replace `wait_for_connection` option with `connection_timeout` --- bindings/nostr-sdk-ffi/src/client/options.rs | 15 ++++++---- bindings/nostr-sdk-ffi/src/relay.rs | 4 +-- bindings/nostr-sdk-js/src/client/options.rs | 15 ++++++---- crates/nostr-sdk/examples/bot.rs | 2 +- crates/nostr-sdk/src/client/mod.rs | 4 +-- crates/nostr-sdk/src/client/options.rs | 24 ++++++++++----- crates/nostr-sdk/src/relay/mod.rs | 31 +++++++++++++------- crates/nostr-sdk/src/relay/pool.rs | 14 ++++----- 8 files changed, 67 insertions(+), 42 deletions(-) diff --git a/bindings/nostr-sdk-ffi/src/client/options.rs b/bindings/nostr-sdk-ffi/src/client/options.rs index 87a3cdfea..0093b41b7 100644 --- a/bindings/nostr-sdk-ffi/src/client/options.rs +++ b/bindings/nostr-sdk-ffi/src/client/options.rs @@ -37,12 +37,6 @@ impl Options { } } - pub fn wait_for_connection(self: Arc, wait: bool) -> Arc { - let mut builder = unwrap_or_clone_arc(self); - builder.inner = builder.inner.wait_for_connection(wait); - Arc::new(builder) - } - pub fn wait_for_send(self: Arc, wait: bool) -> Arc { let mut builder = unwrap_or_clone_arc(self); builder.inner = builder.inner.wait_for_send(wait); @@ -79,6 +73,15 @@ impl Options { Arc::new(builder) } + /// Connection timeout (default: None) + /// + /// If set to `None`, the client will try to connect to the relays without waiting. + pub fn connection_timeout(self: Arc, timeout: Option) -> Arc { + let mut builder = unwrap_or_clone_arc(self); + builder.inner = builder.inner.connection_timeout(timeout); + Arc::new(builder) + } + pub fn send_timeout(self: Arc, send_timeout: Option) -> Arc { let mut builder = unwrap_or_clone_arc(self); builder.inner = builder.inner.send_timeout(send_timeout); diff --git a/bindings/nostr-sdk-ffi/src/relay.rs b/bindings/nostr-sdk-ffi/src/relay.rs index 9c5728bae..5b0d22a87 100644 --- a/bindings/nostr-sdk-ffi/src/relay.rs +++ b/bindings/nostr-sdk-ffi/src/relay.rs @@ -168,8 +168,8 @@ impl Relay { self.inner.queue() as u64 } - pub fn connect(&self, wait_for_connection: bool) { - block_on(self.inner.connect(wait_for_connection)) + pub fn connect(&self, connection_timeout: Option) { + block_on(self.inner.connect(connection_timeout)) } pub fn stop(&self) -> Result<()> { diff --git a/bindings/nostr-sdk-js/src/client/options.rs b/bindings/nostr-sdk-js/src/client/options.rs index a15f3b667..36dbc348e 100644 --- a/bindings/nostr-sdk-js/src/client/options.rs +++ b/bindings/nostr-sdk-js/src/client/options.rs @@ -37,11 +37,6 @@ impl JsOptions { } } - #[wasm_bindgen(js_name = waitForConnection)] - pub fn wait_for_connection(self, wait: bool) -> Self { - self.inner.wait_for_connection(wait).into() - } - #[wasm_bindgen(js_name = waitForSend)] pub fn wait_for_send(self, wait: bool) -> Self { self.inner.wait_for_send(wait).into() @@ -72,6 +67,16 @@ impl JsOptions { self.inner.timeout(**timeout).into() } + /// Connection timeout (default: None) + /// + /// If set to `None`, the client will try to connect to the relays without waiting. + #[wasm_bindgen(js_name = connectionTimeout)] + pub fn connection_timeout(self, connection_timeout: Option) -> Self { + self.inner + .connection_timeout(connection_timeout.map(|d| *d)) + .into() + } + #[wasm_bindgen(js_name = sendTimeout)] pub fn send_timeout(self, send_timeout: Option) -> Self { self.inner.send_timeout(send_timeout.map(|d| *d)).into() diff --git a/crates/nostr-sdk/examples/bot.rs b/crates/nostr-sdk/examples/bot.rs index ed3d38fac..5bc3524ae 100644 --- a/crates/nostr-sdk/examples/bot.rs +++ b/crates/nostr-sdk/examples/bot.rs @@ -15,8 +15,8 @@ async fn main() -> Result<()> { let secret_key = SecretKey::from_bech32(BECH32_SK)?; let keys = Keys::new(secret_key); let opts = Options::new() - .wait_for_connection(true) .skip_disconnected_relays(true) + .connection_timeout(Some(Duration::from_secs(10))) .send_timeout(Some(Duration::from_secs(5))); let client = Client::with_opts(&keys, opts); diff --git a/crates/nostr-sdk/src/client/mod.rs b/crates/nostr-sdk/src/client/mod.rs index de4373ac7..f48d072e5 100644 --- a/crates/nostr-sdk/src/client/mod.rs +++ b/crates/nostr-sdk/src/client/mod.rs @@ -424,7 +424,7 @@ impl Client { { let relay: Relay = self.relay(url).await?; self.pool - .connect_relay(&relay, self.opts.wait_for_connection) + .connect_relay(&relay, self.opts.connection_timeout) .await; Ok(()) } @@ -469,7 +469,7 @@ impl Client { /// # } /// ``` pub async fn connect(&self) { - self.pool.connect(self.opts.wait_for_connection).await; + self.pool.connect(self.opts.connection_timeout).await; } /// Disconnect from all relays diff --git a/crates/nostr-sdk/src/client/options.rs b/crates/nostr-sdk/src/client/options.rs index d445c7dc9..1a12c397c 100644 --- a/crates/nostr-sdk/src/client/options.rs +++ b/crates/nostr-sdk/src/client/options.rs @@ -17,8 +17,6 @@ pub(crate) const DEFAULT_SEND_TIMEOUT: Duration = Duration::from_secs(20); /// Options #[derive(Debug, Clone)] pub struct Options { - /// Wait for connection (default: false) - pub wait_for_connection: bool, /// Wait for the msg to be sent (default: true) wait_for_send: Arc, /// Wait for the subscription msg to be sent (default: false) @@ -35,6 +33,10 @@ pub struct Options { /// /// Used in `get_events_of`, `req_events_of` and similar as default timeout. pub timeout: Duration, + /// Relay connection timeout (default: None) + /// + /// If set to `None`, the client will try to connect to relay without waiting. + pub connection_timeout: Option, /// Send timeout (default: 20 secs) pub send_timeout: Option, /// NIP46 timeout (default: 180 secs) @@ -52,13 +54,13 @@ pub struct Options { impl Default for Options { fn default() -> Self { Self { - wait_for_connection: false, wait_for_send: Arc::new(AtomicBool::new(true)), wait_for_subscription: Arc::new(AtomicBool::new(false)), difficulty: Arc::new(AtomicU8::new(0)), req_filters_chunk_size: Arc::new(AtomicU8::new(10)), skip_disconnected_relays: Arc::new(AtomicBool::new(true)), timeout: Duration::from_secs(60), + connection_timeout: None, send_timeout: Some(DEFAULT_SEND_TIMEOUT), #[cfg(feature = "nip46")] nip46_timeout: Some(Duration::from_secs(180)), @@ -77,11 +79,9 @@ impl Options { } /// If set to `true`, `Client` wait that `Relay` try at least one time to enstablish a connection before continue. - pub fn wait_for_connection(self, wait: bool) -> Self { - Self { - wait_for_connection: wait, - ..self - } + #[deprecated(since = "0.27.0", note = "Use `connection_timeout` instead")] + pub fn wait_for_connection(self, _wait: bool) -> Self { + self } /// If set to `true`, `Client` wait that a message is sent before continue. @@ -157,6 +157,14 @@ impl Options { Self { timeout, ..self } } + /// Connection timeout (default: None) + /// + /// If set to `None`, the client will try to connect to the relays without waiting. + pub fn connection_timeout(mut self, timeout: Option) -> Self { + self.connection_timeout = timeout; + self + } + /// Set default send timeout pub fn send_timeout(self, timeout: Option) -> Self { Self { diff --git a/crates/nostr-sdk/src/relay/mod.rs b/crates/nostr-sdk/src/relay/mod.rs index a66a016b4..98b795e59 100644 --- a/crates/nostr-sdk/src/relay/mod.rs +++ b/crates/nostr-sdk/src/relay/mod.rs @@ -436,7 +436,7 @@ impl Relay { } /// Connect to relay and keep alive connection - pub async fn connect(&self, wait_for_connection: bool) { + pub async fn connect(&self, connection_timeout: Option) { self.schedule_for_stop(false); self.schedule_for_termination(false); @@ -444,13 +444,13 @@ impl Relay { self.status().await { if self.opts.get_reconnect() { - if wait_for_connection { - self.try_connect().await + if connection_timeout.is_some() { + self.try_connect(connection_timeout).await } tracing::debug!("Auto connect loop started for {}", self.url); - if !wait_for_connection { + if connection_timeout.is_none() { self.set_status(RelayStatus::Pending).await; } @@ -491,7 +491,9 @@ impl Relay { match relay.status().await { RelayStatus::Initialized | RelayStatus::Pending - | RelayStatus::Disconnected => relay.try_connect().await, + | RelayStatus::Disconnected => { + relay.try_connect(connection_timeout).await + } RelayStatus::Stopped | RelayStatus::Terminated => { tracing::debug!("Auto connect loop terminated for {}", relay.url); break; @@ -518,16 +520,16 @@ impl Relay { thread::sleep(Duration::from_secs(retry_sec)).await; } }); - } else if wait_for_connection { - self.try_connect().await + } else if connection_timeout.is_some() { + self.try_connect(connection_timeout).await } else { let relay = self.clone(); - thread::spawn(async move { relay.try_connect().await }); + thread::spawn(async move { relay.try_connect(connection_timeout).await }); } } } - async fn try_connect(&self) { + async fn try_connect(&self, connection_timeout: Option) { self.stats.new_attempt(); let url: String = self.url.to_string(); @@ -556,10 +558,17 @@ impl Relay { }); } + let timeout: Option = if self.stats.attempts() > 1 { + // Many attempts, use the default timeout + Some(Duration::from_secs(60)) + } else { + // First attempt, use external timeout + connection_timeout + }; #[cfg(not(target_arch = "wasm32"))] - let connection = net::native::connect(&self.url, self.proxy(), None).await; + let connection = net::native::connect(&self.url, self.proxy(), timeout).await; #[cfg(target_arch = "wasm32")] - let connection = net::wasm::connect(&self.url).await; + let connection = net::wasm::connect(&self.url, timeout).await; // Connect match connection { diff --git a/crates/nostr-sdk/src/relay/pool.rs b/crates/nostr-sdk/src/relay/pool.rs index 9d89c3aed..7f73febe2 100644 --- a/crates/nostr-sdk/src/relay/pool.rs +++ b/crates/nostr-sdk/src/relay/pool.rs @@ -854,16 +854,16 @@ impl RelayPool { } /// Connect to all added relays and keep connection alive - pub async fn connect(&self, wait_for_connection: bool) { + pub async fn connect(&self, connection_timeout: Option) { let relays: HashMap = self.relays().await; - if wait_for_connection { - let mut handles = Vec::new(); + if connection_timeout.is_some() { + let mut handles = Vec::with_capacity(relays.len()); for relay in relays.into_values() { let pool = self.clone(); let handle = thread::spawn(async move { - pool.connect_relay(&relay, wait_for_connection).await; + pool.connect_relay(&relay, connection_timeout).await; }); handles.push(handle); } @@ -873,7 +873,7 @@ impl RelayPool { } } else { for relay in relays.values() { - self.connect_relay(relay, wait_for_connection).await; + self.connect_relay(relay, None).await; } } } @@ -890,12 +890,12 @@ impl RelayPool { /// Connect to relay /// /// Internal Subscription ID set to `InternalSubscriptionId::Pool` - pub async fn connect_relay(&self, relay: &Relay, wait_for_connection: bool) { + pub async fn connect_relay(&self, relay: &Relay, connection_timeout: Option) { let filters: Vec = self.subscription_filters().await; relay .update_subscription_filters(InternalSubscriptionId::Pool, filters) .await; - relay.connect(wait_for_connection).await; + relay.connect(connection_timeout).await; } /// Disconnect from relay