rust-web3
rust-web3 copied to clipboard
Timeouts for websocket transport
Currently having issues where web3 cannot detect if geth goes down while connected via websocket, and requests will just hang.
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.
Should probably a wrapper transport that uses future::select to resolve either to an error (timeout) or to actual future.
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 Happy to review & accept a PR or mentor on the topic, don't have enough time to do it myself though.
@tomusdrw I would like to do this. Can you mentor me on the topic to get started ? Thanks !
@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 {}
ok, checking this !