Tokio 0.3 Upgrade (#2319)
Co-authored-by: Urhengulas <johann.hemmann@code.berlin> Co-authored-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
@@ -967,9 +967,8 @@ mod tests {
|
||||
*conn.io.read_buf_mut() = ::bytes::BytesMut::from(&s[..]);
|
||||
conn.state.cached_headers = Some(HeaderMap::with_capacity(2));
|
||||
|
||||
let mut rt = tokio::runtime::Builder::new()
|
||||
let rt = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.basic_scheduler()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
|
||||
@@ -382,7 +382,7 @@ mod tests {
|
||||
use super::*;
|
||||
use std::pin::Pin;
|
||||
use std::time::Duration;
|
||||
use tokio::io::AsyncRead;
|
||||
use tokio::io::{AsyncRead, ReadBuf};
|
||||
|
||||
impl<'a> MemRead for &'a [u8] {
|
||||
fn read_mem(&mut self, _: &mut task::Context<'_>, len: usize) -> Poll<io::Result<Bytes>> {
|
||||
@@ -401,8 +401,9 @@ mod tests {
|
||||
impl<'a> MemRead for &'a mut (dyn AsyncRead + Unpin) {
|
||||
fn read_mem(&mut self, cx: &mut task::Context<'_>, len: usize) -> Poll<io::Result<Bytes>> {
|
||||
let mut v = vec![0; len];
|
||||
let n = ready!(Pin::new(self).poll_read(cx, &mut v)?);
|
||||
Poll::Ready(Ok(Bytes::copy_from_slice(&v[..n])))
|
||||
let mut buf = ReadBuf::new(&mut v);
|
||||
ready!(Pin::new(self).poll_read(cx, &mut buf)?);
|
||||
Poll::Ready(Ok(Bytes::copy_from_slice(&buf.filled())))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,7 +624,7 @@ mod tests {
|
||||
#[cfg(feature = "nightly")]
|
||||
#[bench]
|
||||
fn bench_decode_chunked_1kb(b: &mut test::Bencher) {
|
||||
let mut rt = new_runtime();
|
||||
let rt = new_runtime();
|
||||
|
||||
const LEN: usize = 1024;
|
||||
let mut vec = Vec::new();
|
||||
@@ -647,7 +648,7 @@ mod tests {
|
||||
#[cfg(feature = "nightly")]
|
||||
#[bench]
|
||||
fn bench_decode_length_1kb(b: &mut test::Bencher) {
|
||||
let mut rt = new_runtime();
|
||||
let rt = new_runtime();
|
||||
|
||||
const LEN: usize = 1024;
|
||||
let content = Bytes::from(&[0; LEN][..]);
|
||||
@@ -665,9 +666,8 @@ mod tests {
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
fn new_runtime() -> tokio::runtime::Runtime {
|
||||
tokio::runtime::Builder::new()
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.basic_scheduler()
|
||||
.build()
|
||||
.expect("rt build")
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ pub(crate) trait Dispatch {
|
||||
type PollError;
|
||||
type RecvItem;
|
||||
fn poll_msg(
|
||||
&mut self,
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut task::Context<'_>,
|
||||
) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Self::PollError>>>;
|
||||
fn recv_msg(&mut self, msg: crate::Result<(Self::RecvItem, Body)>) -> crate::Result<()>;
|
||||
@@ -40,8 +40,10 @@ pub struct Server<S: HttpService<B>, B> {
|
||||
pub(crate) service: S,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
pub struct Client<B> {
|
||||
callback: Option<crate::client::dispatch::Callback<Request<B>, Response<Body>>>,
|
||||
#[pin]
|
||||
rx: ClientRx<B>,
|
||||
rx_closed: bool,
|
||||
}
|
||||
@@ -281,7 +283,7 @@ where
|
||||
&& self.conn.can_write_head()
|
||||
&& self.dispatch.should_poll()
|
||||
{
|
||||
if let Some(msg) = ready!(self.dispatch.poll_msg(cx)) {
|
||||
if let Some(msg) = ready!(Pin::new(&mut self.dispatch).poll_msg(cx)) {
|
||||
let (head, mut body) = msg.map_err(crate::Error::new_user_service)?;
|
||||
|
||||
// Check if the body knows its full data immediately.
|
||||
@@ -469,10 +471,11 @@ where
|
||||
type RecvItem = RequestHead;
|
||||
|
||||
fn poll_msg(
|
||||
&mut self,
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut task::Context<'_>,
|
||||
) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Self::PollError>>> {
|
||||
let ret = if let Some(ref mut fut) = self.in_flight.as_mut().as_pin_mut() {
|
||||
let mut this = self.as_mut();
|
||||
let ret = if let Some(ref mut fut) = this.in_flight.as_mut().as_pin_mut() {
|
||||
let resp = ready!(fut.as_mut().poll(cx)?);
|
||||
let (parts, body) = resp.into_parts();
|
||||
let head = MessageHead {
|
||||
@@ -486,7 +489,7 @@ where
|
||||
};
|
||||
|
||||
// Since in_flight finished, remove it
|
||||
self.in_flight.set(None);
|
||||
this.in_flight.set(None);
|
||||
ret
|
||||
}
|
||||
|
||||
@@ -540,11 +543,12 @@ where
|
||||
type RecvItem = ResponseHead;
|
||||
|
||||
fn poll_msg(
|
||||
&mut self,
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut task::Context<'_>,
|
||||
) -> Poll<Option<Result<(Self::PollItem, Self::PollBody), Never>>> {
|
||||
debug_assert!(!self.rx_closed);
|
||||
match self.rx.poll_next(cx) {
|
||||
let this = self.project();
|
||||
debug_assert!(!*this.rx_closed);
|
||||
match this.rx.poll_next(cx) {
|
||||
Poll::Ready(Some((req, mut cb))) => {
|
||||
// check that future hasn't been canceled already
|
||||
match cb.poll_canceled(cx) {
|
||||
@@ -559,7 +563,7 @@ where
|
||||
subject: RequestLine(parts.method, parts.uri),
|
||||
headers: parts.headers,
|
||||
};
|
||||
self.callback = Some(cb);
|
||||
*this.callback = Some(cb);
|
||||
Poll::Ready(Some(Ok((head, body))))
|
||||
}
|
||||
}
|
||||
@@ -567,7 +571,7 @@ where
|
||||
Poll::Ready(None) => {
|
||||
// user has dropped sender handle
|
||||
trace!("client tx closed");
|
||||
self.rx_closed = true;
|
||||
*this.rx_closed = true;
|
||||
Poll::Ready(None)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::fmt;
|
||||
use std::io::{self, IoSlice};
|
||||
|
||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
|
||||
use super::{Http1Transaction, ParseContext, ParsedMessage};
|
||||
use crate::common::buf::BufList;
|
||||
@@ -188,9 +188,16 @@ where
|
||||
if self.read_buf_remaining_mut() < next {
|
||||
self.read_buf.reserve(next);
|
||||
}
|
||||
match Pin::new(&mut self.io).poll_read_buf(cx, &mut self.read_buf) {
|
||||
Poll::Ready(Ok(n)) => {
|
||||
debug!("read {} bytes", n);
|
||||
let mut buf = ReadBuf::uninit(&mut self.read_buf.bytes_mut()[..]);
|
||||
match Pin::new(&mut self.io).poll_read(cx, &mut buf) {
|
||||
Poll::Ready(Ok(_)) => {
|
||||
let n = buf.filled().len();
|
||||
unsafe {
|
||||
// Safety: we just read that many bytes into the
|
||||
// uninitialized part of the buffer, so this is okay.
|
||||
// @tokio pls give me back `poll_read_buf` thanks
|
||||
self.read_buf.advance_mut(n);
|
||||
}
|
||||
self.read_buf_strategy.record(n);
|
||||
Poll::Ready(Ok(n))
|
||||
}
|
||||
@@ -224,8 +231,16 @@ where
|
||||
return self.poll_flush_flattened(cx);
|
||||
}
|
||||
loop {
|
||||
let n =
|
||||
ready!(Pin::new(&mut self.io).poll_write_buf(cx, &mut self.write_buf.auto()))?;
|
||||
// TODO(eliza): this basically ignores all of `WriteBuf`...put
|
||||
// back vectored IO and `poll_write_buf` when the appropriate Tokio
|
||||
// changes land...
|
||||
let n = ready!(Pin::new(&mut self.io)
|
||||
// .poll_write_buf(cx, &mut self.write_buf.auto()))?;
|
||||
.poll_write(cx, self.write_buf.auto().bytes()))?;
|
||||
// TODO(eliza): we have to do this manually because
|
||||
// `poll_write_buf` doesn't exist in Tokio 0.3 yet...when
|
||||
// `poll_write_buf` comes back, the manual advance will need to leave!
|
||||
self.write_buf.advance(n);
|
||||
debug!("flushed {} bytes", n);
|
||||
if self.write_buf.remaining() == 0 {
|
||||
break;
|
||||
@@ -452,6 +467,7 @@ where
|
||||
self.strategy = strategy;
|
||||
}
|
||||
|
||||
// TODO(eliza): put back writev!
|
||||
#[inline]
|
||||
fn auto(&mut self) -> WriteBufAuto<'_, B> {
|
||||
WriteBufAuto::new(self)
|
||||
@@ -628,28 +644,31 @@ mod tests {
|
||||
*/
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn iobuf_write_empty_slice() {
|
||||
// First, let's just check that the Mock would normally return an
|
||||
// error on an unexpected write, even if the buffer is empty...
|
||||
let mut mock = Mock::new().build();
|
||||
futures_util::future::poll_fn(|cx| {
|
||||
Pin::new(&mut mock).poll_write_buf(cx, &mut Cursor::new(&[]))
|
||||
})
|
||||
.await
|
||||
.expect_err("should be a broken pipe");
|
||||
// TODO(eliza): can i have writev back pls T_T
|
||||
// // First, let's just check that the Mock would normally return an
|
||||
// // error on an unexpected write, even if the buffer is empty...
|
||||
// let mut mock = Mock::new().build();
|
||||
// futures_util::future::poll_fn(|cx| {
|
||||
// Pin::new(&mut mock).poll_write_buf(cx, &mut Cursor::new(&[]))
|
||||
// })
|
||||
// .await
|
||||
// .expect_err("should be a broken pipe");
|
||||
|
||||
// underlying io will return the logic error upon write,
|
||||
// so we are testing that the io_buf does not trigger a write
|
||||
// when there is nothing to flush
|
||||
let mock = Mock::new().build();
|
||||
let mut io_buf = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
|
||||
io_buf.flush().await.expect("should short-circuit flush");
|
||||
// // underlying io will return the logic error upon write,
|
||||
// // so we are testing that the io_buf does not trigger a write
|
||||
// // when there is nothing to flush
|
||||
// let mock = Mock::new().build();
|
||||
// let mut io_buf = Buffered::<_, Cursor<Vec<u8>>>::new(mock);
|
||||
// io_buf.flush().await.expect("should short-circuit flush");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn parse_reads_until_blocked() {
|
||||
use crate::proto::h1::ClientTransaction;
|
||||
|
||||
let _ = pretty_env_logger::try_init();
|
||||
let mock = Mock::new()
|
||||
// Split over multiple reads will read all of it
|
||||
.read(b"HTTP/1.1 200 OK\r\n")
|
||||
|
||||
@@ -33,7 +33,7 @@ use std::time::Instant;
|
||||
|
||||
use h2::{Ping, PingPong};
|
||||
#[cfg(feature = "runtime")]
|
||||
use tokio::time::{Delay, Instant};
|
||||
use tokio::time::{Instant, Sleep};
|
||||
|
||||
type WindowSize = u32;
|
||||
|
||||
@@ -60,7 +60,7 @@ pub(super) fn channel(ping_pong: PingPong, config: Config) -> (Recorder, Ponger)
|
||||
interval,
|
||||
timeout: config.keep_alive_timeout,
|
||||
while_idle: config.keep_alive_while_idle,
|
||||
timer: tokio::time::delay_for(interval),
|
||||
timer: tokio::time::sleep(interval),
|
||||
state: KeepAliveState::Init,
|
||||
});
|
||||
|
||||
@@ -156,7 +156,7 @@ struct KeepAlive {
|
||||
while_idle: bool,
|
||||
|
||||
state: KeepAliveState,
|
||||
timer: Delay,
|
||||
timer: Sleep,
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime")]
|
||||
|
||||
Reference in New Issue
Block a user