use tsoracle_core::Epoch;
#[derive(Debug, thiserror::Error)]
pub enum ConsensusError {
#[error("not leader (current epoch: {observed:?})")]
NotLeader { observed: Option<Epoch> },
#[error("epoch fenced: expected {expected:?}, current {current:?}")]
Fenced { expected: Epoch, current: Epoch },
#[error("transient driver error: {0}")]
TransientDriver(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("permanent driver error: {0}")]
PermanentDriver(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("high-water advance {0} exceeds the 46-bit physical_ms maximum")]
AdvanceOutOfRange(u64),
#[error("dense sequences are not supported by this driver")]
DenseUnsupported,
#[error("dense key-cardinality cap {cap} reached")]
SeqKeyCardinalityExceeded { cap: u64 },
#[error("dense counter overflow for the requested key")]
SeqOverflow,
#[error(
"dense sequences require write version {required} but the cluster is at {active}; activate the format first"
)]
DenseNotActivated { required: u8, active: u8 },
#[error(
"dense batch sequences require write version {required} but the cluster is at {active}; activate the format first"
)]
DenseBatchNotActivated { required: u8, active: u8 },
#[error("leases are not supported by this driver")]
LeasesUnsupported,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn consensus_error_display_text() {
let not_leader = ConsensusError::NotLeader {
observed: Some(Epoch(3)),
};
assert!(not_leader.to_string().contains("not leader"));
let fenced = ConsensusError::Fenced {
expected: Epoch(2),
current: Epoch(5),
};
let fenced_text = fenced.to_string();
assert!(fenced_text.contains("fenced"));
assert!(fenced_text.contains('2'));
assert!(fenced_text.contains('5'));
let transient = ConsensusError::TransientDriver(Box::new(std::io::Error::other("flap")));
assert!(transient.to_string().contains("transient"));
assert!(transient.to_string().contains("flap"));
let permanent = ConsensusError::PermanentDriver(Box::new(std::io::Error::other("corrupt")));
assert!(permanent.to_string().contains("permanent"));
assert!(permanent.to_string().contains("corrupt"));
let out_of_range = ConsensusError::AdvanceOutOfRange(tsoracle_core::PHYSICAL_MS_MAX + 1);
let oor_text = out_of_range.to_string();
assert!(oor_text.contains("high-water advance"));
assert!(oor_text.contains("46-bit"));
assert!(oor_text.contains(&(tsoracle_core::PHYSICAL_MS_MAX + 1).to_string()));
}
}