use thiserror::Error;
#[derive(Debug, Error)]
pub enum DbError {
#[error(transparent)]
Core(#[from] chronix_core::ChronixError),
#[error("Schema error: {0}")]
Schema(#[from] chronix_core::SchemaError),
#[error("Config error: {0}")]
Config(#[from] chronix_core::ConfigError),
#[error("WAL error: {0}")]
Wal(#[from] chronix_core::WalError),
#[error("Encoding error: {0}")]
Encoding(#[from] chronix_encoding::EncodingError),
#[error("Segment error: {0}")]
Segment(#[from] chronix_engine::segment::SegmentError),
#[error("Memtable error: {0}")]
Memtable(#[from] chronix_engine::memtable::MemtableError),
#[error("Storage error: {0}")]
Storage(#[from] chronix_engine::storage::StorageError),
#[error("Index error: {0}")]
Index(#[from] chronix_engine::index::IndexError),
#[error("Query error: {0}")]
Query(#[from] chronix_query::QueryError),
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[cfg(feature = "sql")]
#[error("SQL error: {0}")]
Sql(#[from] datafusion::error::DataFusionError),
#[error("PromQL error: {0}")]
PromQl(String),
#[error("Database is closed")]
Closed,
#[error("Failed to acquire database lock on {path}: another process holds the lock")]
LockFailed {
path: String,
},
#[error("Internal error: {0}")]
Internal(String),
#[error("{0}")]
InvalidRequest(String),
#[error("no {kind} named {name:?}")]
NotFound {
kind: &'static str,
name: String,
},
#[error("{kind} {name:?} already exists")]
Conflict {
kind: &'static str,
name: String,
},
#[error(
"Series cardinality limit exceeded: {current} unique series \
(limit: {limit})"
)]
CardinalityExceeded {
current: usize,
limit: usize,
},
#[error("Query timeout: execution exceeded {0:?}")]
QueryTimeout(std::time::Duration),
#[error("timestamp {timestamp} is beyond the future-write limit {limit}")]
FutureTimestamp {
timestamp: i64,
limit: i64,
},
#[error("Transient overload: {reason} (retry after backoff)")]
TransientOverload {
reason: String,
},
#[error("Persistent overload: {reason} (operator attention required)")]
PersistentOverload {
reason: String,
},
}
#[must_use = "an insert can be partial — check `is_complete()` or `rejected`"]
#[derive(Debug, Default)]
pub struct InsertResult {
pub accepted: usize,
pub rejected: Vec<(usize, DbError)>,
}
impl InsertResult {
pub fn is_complete(&self) -> bool {
self.rejected.is_empty()
}
pub fn is_partial(&self) -> bool {
!self.rejected.is_empty()
}
pub fn into_complete(self) -> Result<usize> {
match self.rejected.into_iter().next() {
None => Ok(self.accepted),
Some((_, err)) => Err(err),
}
}
}
pub type Result<T> = std::result::Result<T, DbError>;