I'm trying to use a tokio Interval to wake up a custom Stream/Sink future (a p2p network stack that tries to reconnect to peers from time to time). The problem is that it panics if used with the default tokio Runtime. I'm using
This panics at runtime with the message there is no timer running, must be called from the context of Tokio runtime. I'm not sure if this is a bug or if I have to activate anything else in the runtime, but from what I saw Runtime::new should enable time features. Do you have any ideas how to fix the problem?
use futures::StreamExt;
#[test]
fn test_interval() {
let mut rt = tokio::runtime::Runtime::new().unwrap();
async fn test(t: Instant) {
eprintln!("Hello World!");
}
// This object is not created inside the runtime.
let future = tokio::time::interval(core::time::Duration::from_secs(1)).for_each(test);
rt.block_on(future);
}
It fails because the object is not created inside the runtime. In this case I would recommend either using #[tokio::test] like this:
Thank you so much I was debugging this for wayyy too long.
But I have to say the implicit data flow gives me creeps (why can't it just use the runtime/context present on first poll instead of requiring it at creation time?). Anyway, that means an async constructor for my custom future or initializing it lazily by creating a builder future on first poll should fix it.
We know the documentation on this is poor, and there are plans to improve both the panic message and the crate documentation on this.
The reason it isn't lazy is that the structure would become more complicated because it now has to handle two states, and this extra state is rarely needed because most users create it inside an async fn anyway. Additionally, it would still have to ask for the current time on creation, which would interact poorly with Tokio's time-mocking feature found in the test-util crate feature.