use std::{error::Error, fmt, io};
#[derive(Debug)]
pub enum PublicationError {
Producer {
source: io::Error,
cleanup_error: Option<io::Error>,
},
BeforePublication {
source: io::Error,
cleanup_error: Option<io::Error>,
},
AfterPublication {
source: io::Error,
},
}
impl PublicationError {
pub(crate) fn from_host(error: ic_host_fs::durable::NamedWriteError<io::Error>) -> Self {
use ic_host_fs::durable::NamedWriteError;
match error {
NamedWriteError::Producer {
source,
cleanup_error,
} => Self::Producer {
source,
cleanup_error,
},
NamedWriteError::BeforePublication {
source,
cleanup_error,
} => Self::BeforePublication {
source,
cleanup_error,
},
NamedWriteError::AfterPublication { source } => Self::AfterPublication { source },
}
}
}
impl fmt::Display for PublicationError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let (description, source, cleanup_error) = match self {
Self::Producer {
source,
cleanup_error,
} => ("staged producer failed", source, cleanup_error.as_ref()),
Self::BeforePublication {
source,
cleanup_error,
} => (
"publication failed before rename",
source,
cleanup_error.as_ref(),
),
Self::AfterPublication { source } => {
("output published but completion failed", source, None)
}
};
write!(formatter, "{description}: {source}")?;
if let Some(cleanup_error) = cleanup_error {
write!(formatter, "; staging cleanup failed: {cleanup_error}")?;
}
Ok(())
}
}
impl Error for PublicationError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Producer { source, .. }
| Self::BeforePublication { source, .. }
| Self::AfterPublication { source } => Some(source),
}
}
}
#[cfg(test)]
mod tests;