Skip to main content

systemprompt_database/
error.rs

1//! Typed error boundary for the database crate.
2//!
3//! `RepositoryError` is the canonical error returned from the crate's
4//! database-facing public signatures, including the dyn-safe
5//! `DatabaseProvider` / `DatabaseTransaction` trait surfaces. It composes
6//! `sqlx::Error` and `serde_json::Error` via `#[from]`; runtime invariant
7//! failures are routed through `RepositoryError::InvalidState`. The
8//! filesystem-only [`crate::squash_baseline`] module carries its own error
9//! type.
10
11use thiserror::Error;
12
13#[derive(Debug, Error)]
14pub enum RepositoryError {
15    #[error("Entity not found: {0}")]
16    NotFound(String),
17
18    #[error("Constraint violation: {0}")]
19    Constraint(String),
20
21    #[error("Database error: {0}")]
22    Database(#[from] sqlx::Error),
23
24    #[error("Serialization error: {0}")]
25    Serialization(#[from] serde_json::Error),
26
27    #[error("Invalid argument: {0}")]
28    InvalidArgument(String),
29
30    #[error("Invalid state: {0}")]
31    InvalidState(String),
32
33    #[error("Internal error: {0}")]
34    Internal(String),
35
36    #[error("Failed to execute query")]
37    QueryExecution(#[source] Box<Self>),
38}
39
40pub type DatabaseResult<T> = Result<T, RepositoryError>;
41
42impl RepositoryError {
43    pub fn not_found<T: std::fmt::Display>(id: T) -> Self {
44        Self::NotFound(id.to_string())
45    }
46
47    pub fn constraint<T: Into<String>>(message: T) -> Self {
48        Self::Constraint(message.into())
49    }
50
51    pub fn invalid_argument<T: Into<String>>(message: T) -> Self {
52        Self::InvalidArgument(message.into())
53    }
54
55    pub fn internal<T: Into<String>>(message: T) -> Self {
56        Self::Internal(message.into())
57    }
58
59    pub fn invalid_state<T: Into<String>>(message: T) -> Self {
60        Self::InvalidState(message.into())
61    }
62
63    #[must_use]
64    pub const fn is_not_found(&self) -> bool {
65        matches!(self, Self::NotFound(_))
66    }
67
68    #[must_use]
69    pub const fn is_constraint(&self) -> bool {
70        matches!(self, Self::Constraint(_))
71    }
72}
73
74impl From<RepositoryError> for systemprompt_traits::RepositoryError {
75    fn from(err: RepositoryError) -> Self {
76        Self::Database(Box::new(err))
77    }
78}