refactor: Start translating server.rs to async await#787
refactor: Start translating server.rs to async await#787Marwes wants to merge 1 commit intomozilla:masterfrom
Conversation
|
This is really interesting, because we kind of thought there was no good way to incrementally transition to new futures. I assume you basically sprinkle @luser is this basically what y'all did internally? |
|
We don't use tokio except for some testing tools so it wasn't as much of a hassle for us. Looks like that's basically what we did for those, though. |
|
Yes. My preferred way is to start from the top, replacing things with async/await/std::fuuture::Future and calling |
glandium
left a comment
There was a problem hiding this comment.
Thank you a lot. I wish it would have been done in smaller increments to ease review, but that's what I failed to do, so 🤷 . Not mentioned in the inline comments: there's a warning about #[macro_use] that you removed in a subsequent patch that should be part of this one.
Cargo.toml
Outdated
| blake3 = "0.1.5" | ||
| byteorder = "1.0" | ||
| bytes = "0.4" | ||
| bytes_05 = { version = "0.5", package = "bytes" } |
There was a problem hiding this comment.
bytes 0.4 is actually unused since 17c56c8, so you don't need the suffix.
| } | ||
| })?; | ||
| .block_on_std(async { time::timeout(Duration::new(30, 0), wait).await }) | ||
| .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; |
There was a problem hiding this comment.
This triggers a warning that should be avoided in this patch rather than later:
594 | / runtime
595 | | .block_on_std(async { time::timeout(Duration::new(30, 0), wait).await })
596 | | .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
| |___________________________________________________________________^
|
= note: `#[warn(unused_must_use)]` on by default
= note: this `Result` may be an `Err` variant, which should be handled
You're kind of addressing this in the last patch, but it feels like it should be addressed here instead. That part of the other patch is too much repeating too. How about changing the Output for WaitUntilZero to () instead of io::Result<()>?
It also looks like for some reason (not sure where this is happening), there's an impl From<tokio::time::Elapsed> for std::io::Error, and removing the map_err works.
| } | ||
| } | ||
|
|
||
| struct BincodeCodec; |
There was a problem hiding this comment.
github doesn't allow to comment on unpatches sections but there's a compile failure in impl<R> futures_03::Stream for Body<R> because the receiver changed type and doesn't have poll anymore. It does have poll_next, though, which simplifies the implementation.
src/server.rs
Outdated
|
|
||
| fn serialize(self: Pin<&mut Self>, item: &T) -> std::result::Result<Bytes, Self::Error> { | ||
| let mut bytes = BytesMut::new(); | ||
| use bytes_05::buf::BufMutExt; |
There was a problem hiding this comment.
This can go at the top of the file.
src/server.rs
Outdated
| Ok(msg.map(Message::WithoutBody).into()) | ||
| fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> { | ||
| Poll::Ready( | ||
| ready!(Stream::poll_next(Pin::new(&mut self.inner), cx)) |
There was a problem hiding this comment.
Is it more idiomatic than Pin::new(&mut self.inner).poll_next(cx)?
src/server.rs
Outdated
| io::Error::new(io::ErrorKind::Other, e) | ||
| })); | ||
| Ok(msg.map(Message::WithoutBody).into()) | ||
| fn poll_next(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> { |
There was a problem hiding this comment.
task::Context is a reexport of std::task::Context, which is imported already, please just use Context.
src/server.rs
Outdated
| future, | ||
| prelude::*, | ||
| ready, stream, | ||
| task::{self, Poll}, |
There was a problem hiding this comment.
Poll is a reexport of std::task::Poll, please import Poll from there instead. As a follow-up, we can replace std::task::Poll with Poll in this file.
src/server.rs
Outdated
| // Shutdown received! | ||
| Async::Ready(Some(ServerMessage::Shutdown)) => return Ok(().into()), | ||
| Async::Ready(Some(ServerMessage::Request)) => { | ||
| Poll::Ready(Some(ServerMessage::Shutdown)) => return ().into(), |
src/server.rs
Outdated
| } | ||
| // All services have shut down, in theory this isn't possible... | ||
| Async::Ready(None) => return Ok(().into()), | ||
| Poll::Ready(None) => return ().into(), |
src/server.rs
Outdated
| .poll() | ||
| .map_err(|err| io::Error::new(io::ErrorKind::Other, err)), | ||
| None => Poll::Pending, | ||
| Some(ref mut timeout) => ready!(Pin::new(timeout).poll(cx)).into(), |
There was a problem hiding this comment.
Is the ready!().into() necessary? I now wonder if that's what was missing in my failed attempt at converting this impl.
There was a problem hiding this comment.
(It wasn't the lack of ready! that made my own attempt fail)
src/errors.rs
Outdated
| TempfilePersist(tempfile::PersistError); | ||
| WalkDir(walkdir::Error); | ||
| Timer(tokio_timer::Error); | ||
| Timeout(tokio::time::Elapsed); |
There was a problem hiding this comment.
This is likely to lose the race against #777 so you may want to rebase on top of that one after it's merged.
| type Response = SccacheResponse; | ||
| type Error = Error; | ||
| type Future = SFuture<Self::Response>; | ||
| type Future = Pin<Box<dyn Future<Output = Result<Self::Response>>>>; |
There was a problem hiding this comment.
A SFuture03 alias would be valuable.
| Message::WithoutBody(Response::ShuttingDown(Box::new(info))) | ||
| })); | ||
| let self_ = self.clone(); | ||
| Box::pin(async move { |
There was a problem hiding this comment.
I'm not particularly convinced using async here is better than not.
There was a problem hiding this comment.
Why? This allows await to be used, making it more flexible.
There was a problem hiding this comment.
It moves some code into a future, and as of right now, I'm not sure this is desired.
| let r: Result<Box<dyn Compiler<C>>> = info.map(|info| info.0); | ||
| r | ||
| } | ||
| } |
| cache_control, | ||
| self.pool.clone(), | ||
| ) | ||
| .compat(); |
There was a problem hiding this comment.
I really hate what rustfmt does when you add .compat(). Not much you can do about though (although you could probably do something like let result = ...; let result = result.compat();). It's just the nth I see and I had to say it.
There was a problem hiding this comment.
compat calls are just temporary 🤷
| res.color_mode = color_mode; | ||
| match result { | ||
| Ok((compiled, out)) => { | ||
| let mut stats = me.stats.borrow_mut(); |
There was a problem hiding this comment.
There's only one Error branch that doesn't use stats. I don't feel it needs to be moved.
There was a problem hiding this comment.
I had to move it to prevent it from living across an await
There was a problem hiding this comment.
Moving it back to where it was compiled just fine for me.
There was a problem hiding this comment.
It may compile fine, but it can still break because another future accessing the RefCell may run if the future yields in the await
|
Should have rebased and squashed these commits before making the PR, don't want to do it now since it messes up reviews. |
Cargo.lock
Outdated
| "bincode", | ||
| "blake3", | ||
| "byteorder", | ||
| "bytes 0.4.12", |
There was a problem hiding this comment.
Why does this not remove the corresponding [[package]] section?
There was a problem hiding this comment.
There are still other dependencies that require bytes 0.4
0113664 to
0a3d55e
Compare
glandium
left a comment
There was a problem hiding this comment.
The nits for this commit were applied in the second commit :(
No description provided.