fatality based errors (#4448)

* seed commit for fatality based errors

* fatality

* first draft of fatality

* cleanup

* differnt approach

* simplify

* first working version for enums, with documentation

* add split

* fix simple split test case

* extend README.md

* update fatality impl

* make tests passed

* apply fatality to first subsystem

* fatality fixes

* use fatality in a subsystem

* fix subsystemg

* fixup proc macro

* fix/test: log::*! do not execute when log handler is missing

* fix spelling

* rename Runtime2 to something sane

* allow nested split with `forward` annotations

* add free license

* enable and fixup all tests

* use external fatality

Makes this more reviewable.

* bump fatality dep

Avoid duplicate expander compilations.

* migrate availability distribution

* more fatality usage

* chore: bump fatality to 0.0.6

* fixup remaining subsystems

* chore: fmt

* make cargo spellcheck happy

* remove single instance of `#[fatal(false)]`

* last quality sweep

* fixup
This commit is contained in:
Bernhard Schuster
2022-02-25 18:25:26 +01:00
committed by GitHub
parent 85fa087405
commit d946582707
48 changed files with 425 additions and 659 deletions
@@ -17,31 +17,17 @@
//! Error handling related code and Error/Result definitions.
use sc_network::PeerId;
use thiserror::Error;
use parity_scale_codec::Error as DecodingError;
/// Errors that happen during reception/decoding of incoming requests.
#[derive(Debug, Error, derive_more::From)]
#[error(transparent)]
#[allow(missing_docs)]
#[fatality::fatality(splitable)]
pub enum Error {
/// All fatal errors.
Fatal(Fatal),
/// All nonfatal/potentially recoverable errors.
NonFatal(NonFatal),
}
/// Fatal errors when receiving incoming requests.
#[derive(Debug, Error)]
pub enum Fatal {
/// Incoming request stream exhausted. Should only happen on shutdown.
// Incoming request stream exhausted. Should only happen on shutdown.
#[fatal]
#[error("Incoming request channel got closed.")]
RequestChannelExhausted,
}
/// Non-fatal errors when receiving incoming requests.
#[derive(Debug, Error)]
pub enum NonFatal {
/// Decoding failed, we were able to change the peer's reputation accordingly.
#[error("Decoding request failed for peer {0}.")]
DecodingError(PeerId, #[source] DecodingError),
@@ -29,7 +29,7 @@ use super::IsRequest;
use crate::UnifiedReputationChange;
mod error;
pub use error::{Error, Fatal, NonFatal, Result};
pub use error::{Error, FatalError, JfyiError, Result};
/// A request coming in, including a sender for sending responses.
///
@@ -84,7 +84,7 @@ where
fn try_from_raw(
raw: sc_network::config::IncomingRequest,
reputation_changes: Vec<UnifiedReputationChange>,
) -> std::result::Result<Self, NonFatal> {
) -> std::result::Result<Self, JfyiError> {
let sc_network::config::IncomingRequest { payload, peer, pending_response } = raw;
let payload = match Req::decode(&mut payload.as_ref()) {
Ok(payload) => payload,
@@ -98,9 +98,9 @@ where
};
if let Err(_) = pending_response.send(response) {
return Err(NonFatal::DecodingErrorNoReputationChange(peer, err))
return Err(JfyiError::DecodingErrorNoReputationChange(peer, err))
}
return Err(NonFatal::DecodingError(peer, err))
return Err(JfyiError::DecodingError(peer, err))
},
};
Ok(Self::new(peer, payload, pending_response))
@@ -224,7 +224,7 @@ where
F: FnOnce() -> Vec<UnifiedReputationChange>,
{
let req = match self.raw.next().await {
None => return Err(Fatal::RequestChannelExhausted.into()),
None => return Err(FatalError::RequestChannelExhausted.into()),
Some(raw) => IncomingRequest::<Req>::try_from_raw(raw, reputation_changes())?,
};
Ok(req)
@@ -15,7 +15,6 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use futures::{channel::oneshot, prelude::Future};
use thiserror::Error;
use parity_scale_codec::{Decode, Encode, Error as DecodingError};
@@ -79,19 +78,19 @@ impl Requests {
pub type ResponseSender = oneshot::Sender<Result<Vec<u8>, network::RequestFailure>>;
/// Any error that can occur when sending a request.
#[derive(Debug, Error)]
#[derive(Debug, thiserror::Error)]
pub enum RequestError {
/// Response could not be decoded.
#[error("Response could not be decoded: {0}")]
InvalidResponse(#[source] DecodingError),
InvalidResponse(#[from] DecodingError),
/// Some error in substrate/libp2p happened.
#[error("{0}")]
NetworkError(#[source] network::RequestFailure),
NetworkError(#[from] network::RequestFailure),
/// Response got canceled by networking.
#[error("Response channel got canceled")]
Canceled(#[source] oneshot::Canceled),
Canceled(#[from] oneshot::Canceled),
}
impl RequestError {
@@ -180,21 +179,3 @@ where
let raw = rec.await??;
Ok(Decode::decode(&mut raw.as_ref())?)
}
impl From<DecodingError> for RequestError {
fn from(err: DecodingError) -> Self {
Self::InvalidResponse(err)
}
}
impl From<network::RequestFailure> for RequestError {
fn from(err: network::RequestFailure) -> Self {
Self::NetworkError(err)
}
}
impl From<oneshot::Canceled> for RequestError {
fn from(err: oneshot::Canceled) -> Self {
Self::Canceled(err)
}
}