hyper icon indicating copy to clipboard operation
hyper copied to clipboard

feat(client, server) make timers generic

Open Robert-Cunningham opened this issue 2 years ago • 6 comments

Hi Sean,

I'm working through the timer series of issues (#2847, #2846, #2848, #2857) right now. This PR isn't (near) done, but I wanted to do a midway check-in and see if you agree with the design decisions, or have any feedback that I can integrate now, relatively early on in the process.

In particular, I'd appreciate any broad design feedback you have on rt.rs or tim.rs.

Otherwise I'll continue moving forwards with this series of issues!

Thanks for your work on hyper!

Robert-Cunningham avatar Jun 24 '22 00:06 Robert-Cunningham

One note: pause, advance and resume from tokio::time control only tokio::time::Instant, not std::time::Instant. If we want to retain the ability to use functions like tokio::time::pause, we need to somehow make all the Instant objects tokio::time::Instant (or potentially any other Instant-ish type for a different library) when the user uses Tokio timers.

If we go that route, I believe we'd need to add functions like Instant::now() to the Timer trait and then and pass Timers around to anywhere we need to call Instant::now().

The alternative is just to use std::time::Instant everywhere and choose not to support functions like tokio::time::pause().

I suspect allowing changes to our Instant type is not worth the additional complexity, but let me know if you think otherwise.

Robert-Cunningham avatar Jun 24 '22 08:06 Robert-Cunningham

Yea I don't want to depend directly on tokio::time::Instant. It might make sense to eventually allow the trait Timer to tell us what the time is, to allow mocking... But I'd probably start with having whatever tests be commented out with a TODO to figure them out later.

seanmonstar avatar Jun 24 '22 20:06 seanmonstar

Alright, I'm now working through the last major hiccup in this PR--would appreciate some guidance here if possible (potentially from @seanmonstar ?).

I have a trait Timer mirroring tokio::time::* with functions like sleep and reset. The last function I need is in Timer is timeout<T>, but I can't include it directly without making Timer object-unsafe. (If Timer becomes object-unsafe, we have to pass it as a generic all over the code base, which I tried before and quickly becomes disgusting.)

I'm trying to cook up a function signature which will allow me to include timeout<T> in the Timer trait, something like fn timeout(&self, duration: Duration, future: Box<dyn Future<Output = Box<dyn Any>>>). Then inside the function I need to do something like tokio::time::timeout(duration, *future), but this doesn't work because future isn't Sized (makes sense).

Do you have any idea how I can include or wrap something similar to tokio::time::timeout<T> in an object-safe Timer trait?

Robert-Cunningham avatar Jul 06 '22 23:07 Robert-Cunningham

@Robert-Cunningham you can write your own timeout function that wraps sleep:

pub fn timeout<F>(duration: Duration, future: F) -> Timeout<F>
where
    F: Future,
{
    Timeout {
        future,
        sleep: sleep(duration),
    }
}


pin_project_lite::pin_project! {
    pub struct Timeout<F> {
        #[pin]
        future: F,
        sleep: Box<dyn Sleep>
    }
}

impl<F> Future for Timeout<F>
where
    F: Future,
{
    type Output = Result<F::Output, TimedOut>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut this = self.project();

        if let Poll::Ready(v) = this.future.poll(cx) {
            return Poll::Ready(Ok(v));
        }

        match Pin::new(&mut this.sleep).poll(cx) {
            Poll::Ready(()) => Poll::Ready(Err(TimedOut)),
            Poll::Pending => Poll::Pending,
        }
    }
}

ibraheemdev avatar Jul 21 '22 03:07 ibraheemdev

Thanks a bunch @ibraheemdev; your answer was instructive for me. With that, I think this PR is ready for review (from @seanmonstar, I think?). Please let me know if I need to do anything else before review; this is my first contribution to hyper.

Once this PR is merged, I'll open a PR that adds the same TokioTimer to hyper-util.

Robert-Cunningham avatar Aug 05 '22 05:08 Robert-Cunningham

Thanks so much for working on this! I'm at RustConf today, but I'll take a look beginning of next week <3

seanmonstar avatar Aug 05 '22 16:08 seanmonstar

Ah, thanks for your feedback--I appreciate the detail. I'm headed to burning man until September 6, but I'm going to try to get this over the goal line before I arrive today.

If I don't manage to finish before I lose cell service, please feel free to make any changes as you see fit and merge--I don't want to stand in the way of progress on 1.0!

Robert-Cunningham avatar Aug 29 '22 21:08 Robert-Cunningham

Thanks so much for taking it this far! I've opened #2974 that rebases this, and I may tweak a little more, and then merge.

seanmonstar avatar Aug 31 '22 23:08 seanmonstar