availability distribution: don't early return on runtime errors (#2606)

* availability distribution: don't early return on runtime errors

* log error

* extract runtime api error from Error

* uh

* oh
This commit is contained in:
Andronik Ordian
2021-03-11 19:47:56 +01:00
committed by GitHub
parent bd2f5b27dd
commit a543b1d6c3
4 changed files with 57 additions and 43 deletions
@@ -34,22 +34,6 @@ pub enum Error {
#[error("Receive channel closed")] #[error("Receive channel closed")]
IncomingMessageChannel(#[source] SubsystemError), IncomingMessageChannel(#[source] SubsystemError),
/// Some request to utility functions failed.
#[error("Runtime request failed")]
UtilRequest(#[source] UtilError),
/// Some request to the runtime failed.
#[error("Runtime request failed")]
RuntimeRequestCanceled(#[source] oneshot::Canceled),
/// Some request to the runtime failed.
#[error("Runtime request failed")]
RuntimeRequest(#[source] RuntimeApiError),
/// We tried fetching a session which was not available.
#[error("No such session")]
NoSuchSession(SessionIndex),
/// Spawning a running task failed. /// Spawning a running task failed.
#[error("Spawning subsystem task failed")] #[error("Spawning subsystem task failed")]
SpawnTask(#[source] SubsystemError), SpawnTask(#[source] SubsystemError),
@@ -71,6 +55,24 @@ pub enum Error {
SendResponse, SendResponse,
} }
/// Error that we should handle gracefully by logging it.
#[derive(Debug)]
pub enum NonFatalError {
/// Some request to utility functions failed.
/// This can be either `RuntimeRequestCanceled` or `RuntimeApiError`.
UtilRequest(UtilError),
/// Runtime API subsystem is down, which means we're shutting down.
RuntimeRequestCanceled(oneshot::Canceled),
/// Some request to the runtime failed.
/// For example if we prune a block we're requesting info about.
RuntimeRequest(RuntimeApiError),
/// We tried fetching a session info which was not available.
NoSuchSession(SessionIndex),
}
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
impl From<SubsystemError> for Error { impl From<SubsystemError> for Error {
@@ -85,9 +87,9 @@ pub(crate) async fn recv_runtime<V>(
oneshot::Receiver<std::result::Result<V, RuntimeApiError>>, oneshot::Receiver<std::result::Result<V, RuntimeApiError>>,
UtilError, UtilError,
>, >,
) -> Result<V> { ) -> std::result::Result<V, NonFatalError> {
r.map_err(Error::UtilRequest)? r.map_err(NonFatalError::UtilRequest)?
.await .await
.map_err(Error::RuntimeRequestCanceled)? .map_err(NonFatalError::RuntimeRequestCanceled)?
.map_err(Error::RuntimeRequest) .map_err(NonFatalError::RuntimeRequest)
} }
@@ -108,10 +108,13 @@ impl AvailabilityDistributionSubsystem {
match message { match message {
FromOverseer::Signal(OverseerSignal::ActiveLeaves(update)) => { FromOverseer::Signal(OverseerSignal::ActiveLeaves(update)) => {
// Update the relay chain heads we are fetching our pieces for: // Update the relay chain heads we are fetching our pieces for:
requester if let Some(e) = requester
.get_mut() .get_mut()
.update_fetching_heads(&mut ctx, update) .update_fetching_heads(&mut ctx, update)
.await?; .await?
{
tracing::debug!(target: LOG_TARGET, "Error processing ActiveLeavesUpdate: {:?}", e);
}
} }
FromOverseer::Signal(OverseerSignal::BlockFinalized(..)) => {} FromOverseer::Signal(OverseerSignal::BlockFinalized(..)) => {}
FromOverseer::Signal(OverseerSignal::Conclude) => { FromOverseer::Signal(OverseerSignal::Conclude) => {
@@ -39,7 +39,8 @@ use polkadot_subsystem::{
messages::AllMessages, ActiveLeavesUpdate, jaeger, SubsystemContext, messages::AllMessages, ActiveLeavesUpdate, jaeger, SubsystemContext,
}; };
use super::{error::recv_runtime, session_cache::SessionCache, Result, LOG_TARGET, Metrics}; use super::{error::recv_runtime, session_cache::SessionCache, LOG_TARGET, Metrics};
use crate::error::NonFatalError;
/// A task fetching a particular chunk. /// A task fetching a particular chunk.
mod fetch_task; mod fetch_task;
@@ -96,7 +97,7 @@ impl Requester {
&mut self, &mut self,
ctx: &mut Context, ctx: &mut Context,
update: ActiveLeavesUpdate, update: ActiveLeavesUpdate,
) -> Result<()> ) -> super::Result<Option<NonFatalError>>
where where
Context: SubsystemContext, Context: SubsystemContext,
{ {
@@ -106,10 +107,9 @@ impl Requester {
} = update; } = update;
// Order important! We need to handle activated, prior to deactivated, otherwise we might // Order important! We need to handle activated, prior to deactivated, otherwise we might
// cancel still needed jobs. // cancel still needed jobs.
self.start_requesting_chunks(ctx, activated.into_iter()) let err = self.start_requesting_chunks(ctx, activated.into_iter()).await?;
.await?;
self.stop_requesting_chunks(deactivated.into_iter()); self.stop_requesting_chunks(deactivated.into_iter());
Ok(()) Ok(err)
} }
/// Start requesting chunks for newly imported heads. /// Start requesting chunks for newly imported heads.
@@ -117,15 +117,20 @@ impl Requester {
&mut self, &mut self,
ctx: &mut Context, ctx: &mut Context,
new_heads: impl Iterator<Item = (Hash, Arc<jaeger::Span>)>, new_heads: impl Iterator<Item = (Hash, Arc<jaeger::Span>)>,
) -> Result<()> ) -> super::Result<Option<NonFatalError>>
where where
Context: SubsystemContext, Context: SubsystemContext,
{ {
for (leaf, _) in new_heads { for (leaf, _) in new_heads {
let cores = query_occupied_cores(ctx, leaf).await?; let cores = match query_occupied_cores(ctx, leaf).await {
self.add_cores(ctx, leaf, cores).await?; Err(err) => return Ok(Some(err)),
Ok(cores) => cores,
};
if let Some(err) = self.add_cores(ctx, leaf, cores).await? {
return Ok(Some(err));
}
} }
Ok(()) Ok(None)
} }
/// Stop requesting chunks for obsolete heads. /// Stop requesting chunks for obsolete heads.
@@ -150,7 +155,7 @@ impl Requester {
ctx: &mut Context, ctx: &mut Context,
leaf: Hash, leaf: Hash,
cores: impl IntoIterator<Item = OccupiedCore>, cores: impl IntoIterator<Item = OccupiedCore>,
) -> Result<()> ) -> super::Result<Option<NonFatalError>>
where where
Context: SubsystemContext, Context: SubsystemContext,
{ {
@@ -165,7 +170,7 @@ impl Requester {
let tx = self.tx.clone(); let tx = self.tx.clone();
let metrics = self.metrics.clone(); let metrics = self.metrics.clone();
let task_cfg = self let task_cfg = match self
.session_cache .session_cache
.with_session_info( .with_session_info(
ctx, ctx,
@@ -175,7 +180,11 @@ impl Requester {
leaf, leaf,
|info| FetchTaskConfig::new(leaf, &core, tx, metrics, info), |info| FetchTaskConfig::new(leaf, &core, tx, metrics, info),
) )
.await?; .await
{
Err(err) => return Ok(Some(err)),
Ok(task_cfg) => task_cfg,
};
if let Some(task_cfg) = task_cfg { if let Some(task_cfg) = task_cfg {
e.insert(FetchTask::start(task_cfg, ctx).await?); e.insert(FetchTask::start(task_cfg, ctx).await?);
@@ -184,7 +193,7 @@ impl Requester {
} }
} }
} }
Ok(()) Ok(None)
} }
} }
@@ -219,7 +228,7 @@ impl Stream for Requester {
async fn query_occupied_cores<Context>( async fn query_occupied_cores<Context>(
ctx: &mut Context, ctx: &mut Context,
relay_parent: Hash, relay_parent: Hash,
) -> Result<Vec<OccupiedCore>> ) -> Result<Vec<OccupiedCore>, NonFatalError>
where where
Context: SubsystemContext, Context: SubsystemContext,
{ {
@@ -33,7 +33,7 @@ use polkadot_primitives::v1::{
use polkadot_subsystem::SubsystemContext; use polkadot_subsystem::SubsystemContext;
use super::{ use super::{
error::{recv_runtime, Result}, error::{recv_runtime, NonFatalError},
Error, Error,
LOG_TARGET, LOG_TARGET,
}; };
@@ -122,7 +122,7 @@ impl SessionCache {
ctx: &mut Context, ctx: &mut Context,
parent: Hash, parent: Hash,
with_info: F, with_info: F,
) -> Result<Option<R>> ) -> Result<Option<R>, NonFatalError>
where where
Context: SubsystemContext, Context: SubsystemContext,
F: FnOnce(&SessionInfo) -> R, F: FnOnce(&SessionInfo) -> R,
@@ -173,7 +173,7 @@ impl SessionCache {
if let Err(err) = self.report_bad(report) { if let Err(err) = self.report_bad(report) {
tracing::warn!( tracing::warn!(
target: LOG_TARGET, target: LOG_TARGET,
err= ?err, err = ?err,
"Reporting bad validators failed with error" "Reporting bad validators failed with error"
); );
} }
@@ -184,7 +184,7 @@ impl SessionCache {
/// We assume validators in a group are tried in reverse order, so the reported bad validators /// We assume validators in a group are tried in reverse order, so the reported bad validators
/// will be put at the beginning of the group. /// will be put at the beginning of the group.
#[tracing::instrument(level = "trace", skip(self, report), fields(subsystem = LOG_TARGET))] #[tracing::instrument(level = "trace", skip(self, report), fields(subsystem = LOG_TARGET))]
pub fn report_bad(&mut self, report: BadValidators) -> Result<()> { pub fn report_bad(&mut self, report: BadValidators) -> super::Result<()> {
let session = self let session = self
.session_info_cache .session_info_cache
.get_mut(&report.session_index) .get_mut(&report.session_index)
@@ -219,7 +219,7 @@ impl SessionCache {
ctx: &mut Context, ctx: &mut Context,
parent: Hash, parent: Hash,
session_index: SessionIndex, session_index: SessionIndex,
) -> Result<Option<SessionInfo>> ) -> Result<Option<SessionInfo>, NonFatalError>
where where
Context: SubsystemContext, Context: SubsystemContext,
{ {
@@ -230,7 +230,7 @@ impl SessionCache {
.. ..
} = recv_runtime(request_session_info_ctx(parent, session_index, ctx).await) } = recv_runtime(request_session_info_ctx(parent, session_index, ctx).await)
.await? .await?
.ok_or(Error::NoSuchSession(session_index))?; .ok_or(NonFatalError::NoSuchSession(session_index))?;
if let Some(our_index) = self.get_our_index(validators).await { if let Some(our_index) = self.get_our_index(validators).await {
// Get our group index: // Get our group index: