use graph_storage_sdk::models::ItemError;
use thiserror::Error;
use toolkit_macros::domain_model;
pub mod reasons {
pub const SCHEMA_VIOLATION: &str = "SCHEMA_VIOLATION";
pub const INVALID_ARGUMENT: &str = "INVALID_ARGUMENT";
pub const LIMIT_COMBINATION: &str = "LIMIT_COMBINATION";
pub const LIMIT_EXCEEDED: &str = "LIMIT_EXCEEDED";
pub const CAS_CONFLICT: &str = "CAS_CONFLICT";
pub const SERIALIZATION: &str = "SERIALIZATION";
pub const STALE_GENERATION: &str = "STALE_GENERATION";
pub const IDEMPOTENCY_MISMATCH: &str = "IDEMPOTENCY_MISMATCH";
pub const IDEMPOTENCY_KEY_EXPIRED: &str = "IDEMPOTENCY_KEY_EXPIRED";
pub const DEADLINE: &str = "DEADLINE";
pub const CANCELLED: &str = "CANCELLED";
pub const CAPABILITY_UNSUPPORTED: &str = "CAPABILITY_UNSUPPORTED";
pub const SCOPE_UNSERVABLE: &str = "SCOPE_UNSERVABLE";
pub const DEPENDENCY_UNAVAILABLE: &str = "DEPENDENCY_UNAVAILABLE";
pub const EMBEDDING_SPACE_MISMATCH: &str = "EMBEDDING_SPACE_MISMATCH";
pub const SOURCE_NAMESPACE_FORBIDDEN: &str = "SOURCE_NAMESPACE_FORBIDDEN";
pub const NOT_FOUND: &str = "NOT_FOUND";
pub const STORE_CORRUPT: &str = "STORE_CORRUPT";
pub const INTERNAL: &str = "INTERNAL";
}
#[domain_model]
#[derive(Debug, Error)]
pub enum DomainError {
#[error("{} item(s) failed validation", items.len())]
Validation { items: Vec<ItemError> },
#[error("invalid argument: {message}")]
InvalidArgument { message: String },
#[error("inconsistent request: {message}")]
LimitCombination { message: String },
#[error("invalid query: {message}")]
InvalidQuery { message: String },
#[error("limit exceeded: {what}")]
LimitExceeded { what: String },
#[error("conflict: {reason}")]
CasConflict { reason: String },
#[error("serialization failure under concurrent ingest")]
Serialization,
#[error("stale source generation: recorded {recorded}, offered {offered}")]
StaleGeneration { recorded: i64, offered: i64 },
#[error("idempotency key reused with a different request")]
IdempotencyMismatch,
#[error("idempotency receipt expired; reconcile and issue a new request")]
IdempotencyExpired,
#[error("not found")]
NotFound,
#[error("access denied")]
AccessDenied,
#[error("source namespace `{namespace}` is owned by another producer")]
SourceNamespaceForbidden { namespace: String },
#[error("no implementation can serve this scope: {reason}")]
ScopeUnservable { reason: String },
#[error("vector search unavailable: {reason}")]
VectorSearchUnavailable { reason: String },
#[error("capability unsupported: {what}")]
Unsupported { what: String },
#[error("dependency unavailable: {detail}")]
Unavailable { detail: String },
#[error("operation exceeded its deadline")]
Deadline,
#[error("operation cancelled")]
Cancelled,
#[error("store corrupt: {reason}")]
Corrupt { reason: String },
#[error("internal error")]
Internal { detail: String },
}
impl DomainError {
pub fn internal(detail: impl Into<String>) -> Self {
Self::Internal {
detail: detail.into(),
}
}
pub fn invalid(message: impl Into<String>) -> Self {
Self::InvalidArgument {
message: message.into(),
}
}
pub fn limit_combination(message: impl Into<String>) -> Self {
Self::LimitCombination {
message: message.into(),
}
}
}
impl From<graph_storage_sdk::plugin_api::GraphStoreError> for DomainError {
fn from(error: graph_storage_sdk::plugin_api::GraphStoreError) -> Self {
use graph_storage_sdk::plugin_api::GraphStoreError as E;
match error {
E::ScopeUnservable { reason } => Self::ScopeUnservable { reason },
E::Unsupported { what } => Self::Unsupported { what: what.into() },
E::Validation { items } => Self::Validation { items },
E::Conflict { reason } => Self::CasConflict { reason },
E::Serialization => Self::Serialization,
E::StaleGeneration { recorded, offered } => Self::StaleGeneration { recorded, offered },
E::IdempotencyMismatch => Self::IdempotencyMismatch,
E::IdempotencyExpired => Self::IdempotencyExpired,
E::NotFound => Self::NotFound,
E::LimitExceeded { what } => Self::LimitExceeded { what },
E::SourceNamespaceForbidden { namespace } => {
Self::SourceNamespaceForbidden { namespace }
}
E::InvalidQuery { what } => Self::InvalidQuery { message: what },
E::Corrupt { reason } => Self::Corrupt { reason },
E::Unavailable { reason } => Self::Unavailable { detail: reason },
E::Deadline => Self::Deadline,
E::Cancelled => Self::Cancelled,
E::Internal(detail) => Self::Internal { detail },
other => Self::Internal {
detail: format!("unclassified store error: {other}"),
},
}
}
}
impl From<graph_storage_sdk::plugin_api::GraphEngineError> for DomainError {
fn from(error: graph_storage_sdk::plugin_api::GraphEngineError) -> Self {
use graph_storage_sdk::plugin_api::GraphEngineError as E;
match error {
E::ScopeNotEnforceable { reason } => Self::ScopeUnservable { reason },
E::Unsupported { what } => Self::Unsupported { what: what.into() },
E::Unavailable { reason } => Self::Unavailable { detail: reason },
E::Deadline => Self::Deadline,
E::Cancelled => Self::Cancelled,
E::Internal(detail) => Self::Internal { detail },
other => Self::Internal {
detail: format!("unclassified engine error: {other}"),
},
}
}
}