rust-web3 icon indicating copy to clipboard operation
rust-web3 copied to clipboard

Timeouts for websocket transport

Open dr-bonez opened this issue 7 years ago • 7 comments

Currently having issues where web3 cannot detect if geth goes down while connected via websocket, and requests will just hang.

dr-bonez avatar Aug 23 '18 19:08 dr-bonez

I'm also looking for how to add timeouts to websockets. I was testing with my parity node being offline and it just waits forever.

BlinkyStitt avatar Sep 27 '18 21:09 BlinkyStitt

Should probably a wrapper transport that uses future::select to resolve either to an error (timeout) or to actual future.

tomusdrw avatar Dec 11 '18 09:12 tomusdrw

Hi I've got a similar problem using Infura websocket and web3 pubsub. The connection seems to get lost after a period of inactivity or just randomly sometimes, and the subscription, while still running/opn, no longer tracks events. Any chance the wrapper transport you mentioned @tomusdrw can be included in the rust-web3 api?

khangle27 avatar Nov 06 '19 19:11 khangle27

@khangle27 Happy to review & accept a PR or mentor on the topic, don't have enough time to do it myself though.

tomusdrw avatar Nov 09 '19 14:11 tomusdrw

@tomusdrw I would like to do this. Can you mentor me on the topic to get started ? Thanks !

EdsonAlcala avatar Nov 20 '20 22:11 EdsonAlcala

@EdsonAlcala great! To be frank, I'm a bit out of the loop with the latest state of rust async runtimes, but after a brief search I couldn't find a runtime-agnostic way of using timeouts, so I guess we need to use two different crates depending on the feature set (async_std and tokio): For tokio: https://docs.rs/tokio/0.3.4/tokio/time/fn.timeout.html For async_std: https://docs.rs/async-std/1.3.0/async_std/future/fn.timeout.html

Luckily the API is the same, so I guess it might be just the import statement that changes. The transport should roughly look like that:

pub struct Timeout<T> {
  transport: T,
  timeout: Duration,
}

impl <O, T: Transport<Out = O>> Transport for Timeout<T> where
 O: Future<...>,
 T: Transport<Out = O>,
{
  type Out = BoxFuture<'static', error::Result<>>;
  // ^^ or we might want to introduce non-boxed type if possible 

  fn send (..) -> Self::Out {
    runtime::timeout(self.timeout.clone(), self.transport.send(id, request)).boxed()
  }
}

// for convenience we might introduce a method to create a transport with timeouts:
pub trait TimeoutExt: Transport + Sized {
  pub fn with_timeout(self, duration: Duration) -> Timeout<Self> {
    Timeout { transport: self, duration }
  }
}
impl<T: Transport + Sized> TimeoutExt for T {}

tomusdrw avatar Nov 24 '20 19:11 tomusdrw

ok, checking this !

EdsonAlcala avatar Nov 25 '20 08:11 EdsonAlcala