use std::error::Error;
use std::io;
use std::path::PathBuf;
use std::sync::Arc;
use thiserror::Error;
use crate::system_state::StateError;
use crate::time_series::StateSeriesError;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum StorageError {
#[error("recording directory `{path}` already exists")]
RecordingDirectoryExists {
path: PathBuf,
},
#[error("invalid storage setting `{setting}`: {reason}")]
InvalidConfiguration {
setting: &'static str,
reason: String,
},
#[error("output stream `{stream}` is configured more than once")]
DuplicateStateStream {
stream: String,
},
#[error("recording does not declare state stream `{stream}`")]
UnknownStateStream {
stream: String,
},
#[error("system-state writer has stopped accepting records")]
StateWriterClosed,
#[error("state recording has already finished")]
RecordingFinished,
#[error("state recording `{path}` is already owned by another writer")]
RecordingDirectoryInUse {
path: PathBuf,
},
#[error("recording metadata `{path}` is terminal and cannot be continued")]
RecordingNotContinuable {
path: PathBuf,
},
#[error("cannot continue recording metadata `{path}`: {reason}")]
RecordingConfigurationMismatch {
path: PathBuf,
reason: String,
},
#[error("stream `{stream}` cannot reconstruct the full system state: {reason}")]
IncompleteCheckpointStream {
stream: String,
reason: String,
},
#[error("stream `{stream}` contains no complete checkpoint record")]
NoCheckpointState {
stream: String,
},
#[error("cannot recover stream output at `{path}`: {reason}")]
RecoveryConflict {
path: PathBuf,
reason: String,
},
#[error(
"metadata file `{path}` uses format version {found}, but this crate supports version {supported}"
)]
UnsupportedVersion {
path: PathBuf,
found: u32,
supported: u32,
},
#[error("invalid recording metadata in `{path}`: {reason}")]
InvalidMetadata {
path: PathBuf,
reason: String,
},
#[error("recording metadata `{path}` does not declare successful completion")]
RecordingNotComplete {
path: PathBuf,
},
#[error("committed chunk `{path}` is missing")]
MissingChunk {
path: PathBuf,
},
#[error("chunk `{path}` has {actual} bytes, but metadata declares {expected}")]
ChunkSizeMismatch {
path: PathBuf,
expected: u64,
actual: u64,
},
#[error("chunk `{path}` checksum is `{actual}`, but metadata declares `{expected}`")]
ChecksumMismatch {
path: PathBuf,
expected: String,
actual: String,
},
#[error("invalid record at line {line} of `{path}`: {reason}")]
InvalidRecord {
path: PathBuf,
line: u64,
reason: String,
},
#[error(
"cannot sample field `{field}` for stream `{stream}` at iteration {iteration}: {source}"
)]
StateAccess {
stream: String,
iteration: u64,
field: String,
#[source]
source: StateError,
},
#[error("failed to encode field `{field}` for stream `{stream}` at iteration {iteration}")]
EncodeField {
stream: String,
iteration: u64,
field: String,
#[source]
source: serde_json::Error,
},
#[error("a payload decoder is already registered for field `{field}`")]
DuplicateDecoder {
field: String,
},
#[error("no payload decoder is registered for field `{field}`")]
MissingDecoder {
field: String,
},
#[error("failed to decode field `{field}` for stream `{stream}` at iteration {iteration}")]
DecodeField {
stream: String,
iteration: u64,
field: String,
#[source]
source: Box<dyn Error + Send + Sync + 'static>,
},
#[error("decoded state for stream `{stream}` at iteration {iteration} cannot enter its series")]
StateSeriesInvariant {
stream: String,
iteration: u64,
#[source]
source: StateSeriesError,
},
#[error("failed to {operation} at `{path}`")]
Io {
operation: &'static str,
path: PathBuf,
#[source]
source: io::Error,
},
#[error("failed to {operation} JSON at `{path}`")]
Json {
operation: &'static str,
path: PathBuf,
#[source]
source: serde_json::Error,
},
#[error("encoded byte count overflowed while processing stream `{stream}`")]
ByteCountOverflow {
stream: String,
},
#[error(
"encoded record for stream `{stream}` has {bytes} bytes, exceeding the queue limit of {limit}"
)]
RecordTooLarge {
stream: String,
bytes: u64,
limit: u64,
},
#[error(
"record iteration {iteration} for stream `{stream}` does not follow previously accepted iteration {previous}"
)]
OutOfOrderIteration {
stream: String,
iteration: u64,
previous: u64,
},
#[error("system-state writer queue disconnected before shutdown completed")]
WriterQueueDisconnected,
#[error("system-state writer terminated: {source}")]
StateWriterTerminated {
#[source]
source: Arc<StorageError>,
},
#[error("system-state writer worker panicked")]
StateWriterPanicked,
}