4

I am trying to introduce a timeout in my RPC requests using tokio:timer:Timeout:

use std::time::{Duration, Instant};
use tokio::prelude::*;
use tokio::timer::Delay;

fn main() {
    let when = Instant::now() + Duration::from_millis(4000);
    let task = Delay::new(when)
        .and_then(|_| {
            println!("Hello world!");
            Ok(())
        })
        .map_err(|e| panic!("delay errored; err={:?}", e));

    let task_with_timeout = task
        .timeout(Duration::from_millis(3000))
        .map_err(|e| println!("Timeout hit {:?}", e));
    let _ = task_with_timeout.wait().expect("Failure");
    // tokio::run(task_with_timeout);
}

If I run my future_with_timeout with tokio::run(), it works as expected.

However, calling wait on the task_with_timeout results in the task future getting an error:

thread 'main' panicked at 'delay errored; err=Error(Shutdown)'

instead of getting

Timeout hit Error(Elapsed)

I don't understand the difference here between using tokio::run() and wait().

Playground link

How do I make the code work using wait?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
pd176
  • 821
  • 3
  • 10
  • 20

1 Answers1

2

I wouldn't, and it's possible that you just can't.

Read the documentation for the timer module:

These types must be used from within the context of the Runtime or a timer context must be setup explicitly. See the tokio-timer crate for more details on how to setup a timer context.

Following the thread, we get to tokio_timer::with_default which requires a Tokio executor and a Timer. The executor uses the Enter type, which itself wants a future to block on.

All of this is to say that Tokio's futures may rely on features outside of the pure executor. If I understand the terms correctly (and it's likely I do not), those features are provided by the reactor. Calling wait has no knowledge of that.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366