pub mod bootstrap {
pub use crate::storage::bootstrap::*;
}
pub mod client;
pub mod comparison;
pub mod query;
pub mod ranking;
pub mod reporting;
mod time {
pub use crate::storage::time::*;
}
#[cfg(test)]
pub mod write {
pub use crate::storage::write::*;
}
#[derive(Debug, thiserror::Error)]
pub enum EngineError {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("native connection lock was poisoned")]
ConnectionLockPoisoned,
#[error("project already exists: {project_id}")]
ProjectAlreadyExists { project_id: String },
#[error("project not found: {project_id}")]
ProjectNotFound { project_id: String },
#[error("run already exists: {run_id}")]
RunAlreadyExists { run_id: String },
#[error("run already has an active writer: {run_id}")]
RunAlreadyActive { run_id: String },
#[error("run not found: {run_id}")]
RunNotFound { run_id: String },
#[error("duplicate run identity in request: {run_id}")]
DuplicateRunIdentity { run_id: String },
#[error("run is closed for metric reporting: {run_id}")]
RunClosed { run_id: String },
#[error("invalid run transition for {run_id}: {from} -> {to}")]
InvalidRunTransition {
run_id: String,
from: &'static str,
to: &'static str,
},
#[error("metric query max_points must be at least 2, got {max_points}")]
MetricQueryMaxPointsTooSmall { max_points: usize },
#[error("metric query max_points is too large for DuckDB LTTB: {max_points}")]
MetricQueryMaxPointsTooLarge { max_points: usize },
#[error("metric queue is full")]
MetricQueueFull,
#[error("timed out waiting for the catalog write lock")]
CatalogWriteLockTimeout,
#[error("unsupported native storage format version {found}; expected {expected}")]
StorageFormatMismatch { expected: i64, found: i64 },
#[error("metric batch must contain between 1 and 8192 points, got {count}")]
InvalidMetricBatch { count: usize },
#[error("committed step {attempted} regresses from cursor {cursor}")]
StepRegression { cursor: i64, attempted: i64 },
#[error("step {step} has no representable successor")]
StepOverflow { step: i64 },
#[error("metric writer failed: {message}")]
MetricWriterFailed { message: String },
#[error("metric drain timed out")]
MetricDrainTimeout,
#[error("metric flush failed: {message}")]
MetricFlush { message: String },
#[error("metric flush timed out")]
MetricFlushTimeout,
#[error("client is closed")]
ClientClosed,
#[error("catalog not found: {name}")]
CatalogNotFound { name: String },
#[error("storage operation failed while {operation}: {name}")]
Storage {
operation: &'static str,
name: String,
#[source]
source: std::io::Error,
},
#[error(transparent)]
StorageFailure(crate::storage::StorageError),
#[error("storage operation failed: {message}")]
StorageLayer { message: String },
#[error("invalid stored run status: {status}")]
InvalidRunStatus { status: String },
#[error("invalid stored timestamp for {field}: {millis}")]
InvalidTimestamp { field: &'static str, millis: i64 },
}
impl From<crate::storage::StorageError> for EngineError {
fn from(error: crate::storage::StorageError) -> Self {
use crate::storage::StorageError;
match error {
error @ StorageError::DuckDb(_) => Self::StorageFailure(error),
StorageError::Io(source) => Self::Io(source),
StorageError::RunAlreadyExists { run_id } => Self::RunAlreadyExists { run_id },
StorageError::RunNotFound { run_id } => Self::RunNotFound { run_id },
StorageError::RunAlreadyActive { run_id } => Self::RunAlreadyActive { run_id },
StorageError::CatalogNotFound { name } => Self::CatalogNotFound { name },
StorageError::CatalogWriteLockTimeout => Self::CatalogWriteLockTimeout,
StorageError::StorageFormatMismatch { expected, found } => {
Self::StorageFormatMismatch { expected, found }
}
StorageError::Storage {
operation,
name,
source,
} => Self::Storage {
operation,
name,
source,
},
error @ StorageError::StorageDuckDb { .. } => Self::StorageFailure(error),
StorageError::QueryMaxPointsTooLarge { max_points } => {
Self::MetricQueryMaxPointsTooLarge { max_points }
}
StorageError::InvalidRunStatus { status } => Self::InvalidRunStatus { status },
StorageError::InvalidTimestamp { field, millis } => {
Self::InvalidTimestamp { field, millis }
}
other => Self::StorageLayer {
message: other.to_string(),
},
}
}
}