use crate::StoreError;
use dpm_model::{
ActivityEntry, LifecycleEntry, LineageId, OperationId, RunId, RunRecord, WorkspaceId,
};
use std::path::PathBuf;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum RunStoreError {
#[error(transparent)]
Store(#[from] StoreError),
#[error(transparent)]
Run(#[from] dpm_engine::RunError),
#[error("run {0} is not recorded")]
UnknownRun(RunId),
#[error("parent run {0} is not recorded")]
UnknownParent(RunId),
#[error("run {} is already recorded with different content; use a new run id for a new run", .recorded.id)]
DuplicateRun {
recorded: Box<RunRecord>,
},
#[error("transition {} is already recorded with different content; use a new event id", .recorded.event.id)]
DuplicateEvent {
recorded: Box<LifecycleEntry>,
},
#[error("activity {} of run {} is already recorded with different content", .recorded.record.source_sequence, .recorded.record.run)]
DuplicateActivity {
recorded: Box<ActivityEntry>,
},
#[error(
"activity {source_sequence} of run {run} is expired: the run's accepted sequences already reach {high_water}, and this one is not retained; sequences must increase"
)]
ActivityExpired {
run: RunId,
source_sequence: u64,
high_water: u64,
},
#[error(
"run {run} was recorded under lineage {recorded}, but this store continues lineage {current}; it is a historical observation and takes no new facts, so start a new run"
)]
ForeignRun {
run: RunId,
recorded: LineageId,
current: LineageId,
},
#[error("operation {operation} is already linked to run {linked}")]
LinkConflict {
operation: OperationId,
linked: RunId,
},
#[error("run store {path} belongs to workspace {actual}, not {expected}; nothing was changed")]
WorkspaceMismatch {
path: PathBuf,
expected: WorkspaceId,
actual: WorkspaceId,
},
#[error("run store {path} is inconsistent: {detail}")]
Corrupt {
path: PathBuf,
detail: String,
},
}
impl RunStoreError {
#[must_use]
pub fn is_corruption(&self) -> bool {
match self {
Self::Store(error) => error.is_corruption(),
Self::Corrupt { .. } => true,
_ => false,
}
}
#[must_use]
pub fn is_busy(&self) -> bool {
matches!(self, Self::Store(error) if error.is_busy())
}
}