use std::io;
#[derive(thiserror::Error, Debug)]
pub enum DbError {
#[error("client error: {0}")]
Client(&'static str),
#[error("key not found")]
KeyNotFound,
#[error("not implemented")]
NotImplemented,
#[error("storage error: {0}")]
Internal(&'static str),
#[error(transparent)]
Io(#[from] io::Error),
#[error("CRC32 mismatch: expected {expected:#x}, got {actual:#x}")]
CrcMismatch { expected: u32, actual: u32 },
#[error("corrupted entry at offset {offset}")]
CorruptedEntry { offset: u64 },
#[error("invalid configuration: {0}")]
Config(&'static str),
#[error("CAS value mismatch")]
CasMismatch,
#[error("key already exists")]
KeyExists,
#[error("all slots are occupied")]
SlotsFull,
#[error("key routes to a different shard")]
ShardMismatch,
#[error("disk format mismatch: {0}")]
FormatMismatch(String),
#[cfg(feature = "encryption")]
#[error("encryption error: {0}")]
EncryptionError(String),
#[cfg(feature = "replication")]
#[error("replication error: {0}")]
Replication(String),
#[cfg(feature = "replication")]
#[error("shard count mismatch: leader has {leader}, follower has {follower}")]
ShardCountMismatch { leader: usize, follower: usize },
}
impl DbError {
pub fn status_code(&self) -> u16 {
match self {
DbError::Client(_) => 400,
DbError::KeyNotFound => 404,
DbError::NotImplemented => 501,
_ => 500,
}
}
pub fn to_resp(&self) -> (u16, &'static str) {
match self {
DbError::Client(msg) => (400, msg),
DbError::KeyNotFound => (404, ""),
DbError::NotImplemented => (501, ""),
_ => {
tracing::error!("{self}");
(500, "")
}
}
}
}
pub type DbResult<T> = Result<T, DbError>;