Return stream to pool on exact read (#509)

If the user reads exactly the number of bytes in the response, then
drops the Read object, streams will never get returned to the pool since
the user never triggered a read past the end of the LimitedRead.

This fixes that by making PoolReturnRead aware of the level below it, so
it can ask if a stream is "done" without actually doing a read.

Also, a refactorign:

Previously, Response contained an Option<Box<Unit>> because the testing
method `from_str()` would construct a Response with no associated Unit.
However, this increased code complexity with no corresponding test
benefit. Instead, construct a fake Unit in from_str().

Also, instead of taking an `Option<Box<Unit>>`, PoolReturnRead now takes
a URL (to figure out host and port for the PoolKey) and an &Agent where
it will return the stream. This cuts interconnectedness somewhat:
PoolReturnRead doesn't need to know about Unit anymore.
This commit is contained in:
Jacob Hoffman-Andrews
2022-04-30 17:22:27 -07:00
committed by GitHub
parent 4d77d365a0
commit 101467f13f
4 changed files with 154 additions and 70 deletions

View File

@@ -69,11 +69,11 @@ impl Inner for TcpStream {
}
}
struct TestStream(Box<dyn Read + Send + Sync>, Vec<u8>);
struct TestStream(Box<dyn Read + Send + Sync>, Vec<u8>, bool);
impl Inner for TestStream {
fn is_poolable(&self) -> bool {
false
self.2
}
fn socket(&self) -> Option<&TcpStream> {
None
@@ -201,7 +201,18 @@ impl Stream {
pub(crate) fn from_vec(v: Vec<u8>) -> Stream {
Stream::logged_create(Stream {
inner: BufReader::new(Box::new(TestStream(Box::new(Cursor::new(v)), vec![]))),
inner: BufReader::new(Box::new(TestStream(
Box::new(Cursor::new(v)),
vec![],
false,
))),
})
}
#[cfg(test)]
pub(crate) fn from_vec_poolable(v: Vec<u8>) -> Stream {
Stream::logged_create(Stream {
inner: BufReader::new(Box::new(TestStream(Box::new(Cursor::new(v)), vec![], true))),
})
}