combine network setup into an exhaustive match
This commit is contained in:
parent
4d6ef89248
commit
4cf331562c
|
|
@ -10,6 +10,7 @@ use futures::{
|
||||||
future::{FutureExt, TryFutureExt},
|
future::{FutureExt, TryFutureExt},
|
||||||
stream::Stream,
|
stream::Stream,
|
||||||
};
|
};
|
||||||
|
use mem::swap;
|
||||||
use oneshot::error::TryRecvError;
|
use oneshot::error::TryRecvError;
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
use tower::{buffer::Buffer, timeout::Timeout, util::BoxService, Service, ServiceExt};
|
use tower::{buffer::Buffer, timeout::Timeout, util::BoxService, Service, ServiceExt};
|
||||||
|
|
@ -131,6 +132,12 @@ impl Inbound {
|
||||||
state,
|
state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn take_setup(&mut self) -> Setup {
|
||||||
|
let mut network = Setup::FailedInit;
|
||||||
|
std::mem::swap(&mut self.network, &mut network);
|
||||||
|
network
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Service<zn::Request> for Inbound {
|
impl Service<zn::Request> for Inbound {
|
||||||
|
|
@ -145,64 +152,58 @@ impl Service<zn::Request> for Inbound {
|
||||||
// and reporting unreadiness might cause unwanted load-shedding, since
|
// and reporting unreadiness might cause unwanted load-shedding, since
|
||||||
// the load-shed middleware is unable to distinguish being unready due
|
// the load-shed middleware is unable to distinguish being unready due
|
||||||
// to load from being unready while waiting on setup.
|
// to load from being unready while waiting on setup.
|
||||||
if matches!(self.network, Setup::AwaitingNetwork { .. }) {
|
let mut result = Ok(());
|
||||||
// Unfortunately, we can't match, swap, and destructure at the same time
|
|
||||||
let mut awaiting_state = Setup::FailedInit;
|
self.network = match self.take_setup() {
|
||||||
mem::swap(&mut self.network, &mut awaiting_state);
|
Setup::AwaitingNetwork {
|
||||||
if let Setup::AwaitingNetwork {
|
|
||||||
mut network_setup,
|
mut network_setup,
|
||||||
verifier,
|
verifier,
|
||||||
} = awaiting_state
|
} => match network_setup.try_recv() {
|
||||||
{
|
Ok((outbound, address_book)) => {
|
||||||
match network_setup.try_recv() {
|
let downloads = Box::pin(Downloads::new(
|
||||||
Ok((outbound, address_book)) => {
|
Timeout::new(outbound, BLOCK_DOWNLOAD_TIMEOUT),
|
||||||
let downloads = Box::pin(Downloads::new(
|
Timeout::new(verifier, BLOCK_VERIFY_TIMEOUT),
|
||||||
Timeout::new(outbound, BLOCK_DOWNLOAD_TIMEOUT),
|
self.state.clone(),
|
||||||
Timeout::new(verifier, BLOCK_VERIFY_TIMEOUT),
|
));
|
||||||
self.state.clone(),
|
Setup::Initialized {
|
||||||
));
|
address_book,
|
||||||
self.network = Setup::Initialized {
|
downloads,
|
||||||
address_book,
|
|
||||||
downloads,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Err(TryRecvError::Empty) => {
|
|
||||||
// There's no setup data yet, so keep waiting for it
|
|
||||||
self.network = Setup::AwaitingNetwork {
|
|
||||||
network_setup,
|
|
||||||
verifier,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Err(error @ TryRecvError::Closed) => {
|
|
||||||
// Mark the service as failed, because network setup failed
|
|
||||||
error!(?error, "inbound network setup failed");
|
|
||||||
let error: SharedRecvError = error.into();
|
|
||||||
self.network = Setup::FailedRecv {
|
|
||||||
error: error.clone(),
|
|
||||||
};
|
|
||||||
return Poll::Ready(Err(error.into()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(TryRecvError::Empty) => {
|
||||||
|
// There's no setup data yet, so keep waiting for it
|
||||||
|
Setup::AwaitingNetwork {
|
||||||
|
network_setup,
|
||||||
|
verifier,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(error @ TryRecvError::Closed) => {
|
||||||
|
// Mark the service as failed, because network setup failed
|
||||||
|
error!(?error, "inbound network setup failed");
|
||||||
|
let error: SharedRecvError = error.into();
|
||||||
|
result = Err(error.clone().into());
|
||||||
|
Setup::FailedRecv { error }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Make sure we left the network setup in a valid state
|
||||||
|
Setup::FailedInit => unreachable!("incomplete Inbound initialization"),
|
||||||
|
// If network setup failed, report service failure
|
||||||
|
Setup::FailedRecv { error } => {
|
||||||
|
result = Err(error.clone().into());
|
||||||
|
Setup::FailedRecv { error }
|
||||||
}
|
}
|
||||||
}
|
// Clean up completed download tasks, ignoring their results
|
||||||
|
Setup::Initialized {
|
||||||
// Unfortunately, we can't combine these matches into an exhaustive match statement,
|
address_book,
|
||||||
// because they use mutable references, or they depend on the state we've just modified.
|
mut downloads,
|
||||||
|
} => {
|
||||||
// Make sure we left the network setup in a valid state
|
while let Poll::Ready(Some(_)) = downloads.as_mut().poll_next(cx) {}
|
||||||
if matches!(self.network, Setup::FailedInit) {
|
Setup::Initialized {
|
||||||
unreachable!("incomplete Inbound initialization");
|
address_book,
|
||||||
}
|
downloads,
|
||||||
|
}
|
||||||
// If network setup failed, report service failure
|
}
|
||||||
if let Setup::FailedRecv { error } = &mut self.network {
|
};
|
||||||
return Poll::Ready(Err(error.clone().into()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up completed download tasks, ignoring their results
|
|
||||||
if let Setup::Initialized { downloads, .. } = &mut self.network {
|
|
||||||
while let Poll::Ready(Some(_)) = downloads.as_mut().poll_next(cx) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// * do we want to propagate backpressure from the download queue or its outbound network?
|
// * do we want to propagate backpressure from the download queue or its outbound network?
|
||||||
|
|
@ -213,7 +214,7 @@ impl Service<zn::Request> for Inbound {
|
||||||
// So we might also want to propagate backpressure from its buffer.
|
// So we might also want to propagate backpressure from its buffer.
|
||||||
// * if we want to propagate backpressure, add a ReadyCache for each service, to ensure
|
// * if we want to propagate backpressure, add a ReadyCache for each service, to ensure
|
||||||
// that each poll_ready has a matching call. See #1593 for details.
|
// that each poll_ready has a matching call. See #1593 for details.
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(name = "inbound", skip(self, req))]
|
#[instrument(name = "inbound", skip(self, req))]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue