use std::num::TryFromIntError;
use thiserror::Error as ThisError;
use crate::meta_storage::MemMetaError;
pub(crate) type MetaResult<T, MErr> = Result<T, MetaStorageError<MErr>>;
#[derive(Debug, ThisError)]
#[non_exhaustive]
pub enum MetaStorageError<MErr> {
#[error("Integer conversion error: {0}")]
IntegerConversionError(#[from] TryFromIntError),
#[error("Invalid run state: {0}")]
InvalidRunState(String),
#[error("Invalid explosion: Called `explode({dim})` on `{task}`, but `{dim}` was resolved.")]
InvalidExplosion {
task: &'static str,
dim: &'static str,
},
#[error("Missing ticket summary for task '{task}'")]
MissingTicketSummary {
task: &'static str,
},
#[error("Missing resolution for dimension `{dim}[{}]`", fmt_deps(.deps))]
MissingResolution {
dim: &'static str,
deps: Vec<(&'static str, usize)>,
},
#[error("Internal error: {0}")]
Internal(&'static str),
#[error("Another Operon instance is already running against metadata schema `{0}`")]
SchemaLocked(String),
#[error(
"Lost the advisory lock on metadata schema `{0}` (connection dropped or lock \
otherwise released); stopping to avoid running unguarded"
)]
LockLost(String),
#[error(transparent)]
Backend(MErr),
#[error("Error from scratch in-memory store used during rebuild: {0}")]
RebuildBackend(MemMetaError),
}
fn fmt_deps(deps: &[(&'static str, usize)]) -> String {
deps.iter()
.map(|(name, val)| format!("{name} = {val}"))
.collect::<Vec<_>>()
.join(", ")
}
impl<MErr> MetaStorageError<MErr> {
pub(crate) fn invalid_explosion(task: &'static str, dim: &'static str) -> Self {
Self::InvalidExplosion { task, dim }
}
pub(crate) fn missing_ticket_summary(task: &'static str) -> Self {
Self::MissingTicketSummary { task }
}
pub(crate) fn and_then_backend<U>(
self,
f: impl FnOnce(MErr) -> MetaStorageError<U>,
) -> MetaStorageError<U> {
match self {
Self::IntegerConversionError(e) => MetaStorageError::IntegerConversionError(e),
Self::InvalidRunState(s) => MetaStorageError::InvalidRunState(s),
Self::InvalidExplosion { task, dim } => {
MetaStorageError::InvalidExplosion { task, dim }
}
Self::MissingTicketSummary { task } => MetaStorageError::MissingTicketSummary { task },
Self::MissingResolution { dim, deps } => {
MetaStorageError::MissingResolution { dim, deps }
}
Self::Internal(s) => MetaStorageError::Internal(s),
Self::RebuildBackend(e) => MetaStorageError::RebuildBackend(e),
Self::SchemaLocked(s) => MetaStorageError::SchemaLocked(s),
Self::LockLost(s) => MetaStorageError::LockLost(s),
Self::Backend(e) => f(e),
}
}
pub(crate) fn map_backend<U>(self, f: impl FnOnce(MErr) -> U) -> MetaStorageError<U> {
self.and_then_backend(|e| MetaStorageError::Backend(f(e)))
}
}
impl MetaStorageError<MemMetaError> {
pub(crate) fn during_rebuild<U>(self) -> MetaStorageError<U> {
self.and_then_backend(MetaStorageError::RebuildBackend)
}
}