diff options
author | Vincent Ambo <mail@tazj.in> | 2020-06-30T03·35+0100 |
---|---|---|
committer | Vincent Ambo <mail@tazj.in> | 2020-06-30T03·35+0100 |
commit | 9e7b81391d016d98ef9b5f0c1f3405bdec31133c (patch) | |
tree | 5310a4a669f6f163df1969bdc44a2b6198363e84 /users/tazjin/finito/finito-postgres/src/error.rs | |
parent | 0380841eb11f6cb200081295107fadbca928bc06 (diff) | |
parent | b7481172252d6f00546e94534b05d011b4105843 (diff) |
feat(tazjin/finito): Check in my old Rust state-machine library r/1136
I dug through my archives for this and found a version that, while unfortunately not the latest implementation, is close enough to the real thing to show off what Finito did. This is a Postgres-backed state-machine library for complex application logic. I wrote this originally for a work purpose in a previous life, but have always wanted to apply it elsewhere, too. git-subtree-dir: users/tazjin/finito git-subtree-mainline: 0380841eb11f6cb200081295107fadbca928bc06 git-subtree-split: b7481172252d6f00546e94534b05d011b4105843 Change-Id: I0de02d6258568447a14870f1a533812a67127763
Diffstat (limited to 'users/tazjin/finito/finito-postgres/src/error.rs')
-rw-r--r-- | users/tazjin/finito/finito-postgres/src/error.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/users/tazjin/finito/finito-postgres/src/error.rs b/users/tazjin/finito/finito-postgres/src/error.rs new file mode 100644 index 000000000000..e130d18361f1 --- /dev/null +++ b/users/tazjin/finito/finito-postgres/src/error.rs @@ -0,0 +1,109 @@ +//! This module defines error types and conversions for issue that can +//! occur while dealing with persisted state machines. + +use std::result; +use std::fmt; +use uuid::Uuid; +use std::error::Error as StdError; + +// errors to chain: +use postgres::Error as PgError; +use r2d2_postgres::r2d2::Error as PoolError; +use serde_json::Error as JsonError; + +pub type Result<T> = result::Result<T, Error>; + +#[derive(Debug)] +pub struct Error { + pub kind: ErrorKind, + pub context: Option<String>, +} + +#[derive(Debug)] +pub enum ErrorKind { + /// Errors occuring during JSON serialization of FSM types. + Serialization(String), + + /// Errors occuring during communication with the database. + Database(String), + + /// Errors with the database connection pool. + DBPool(String), + + /// State machine could not be found. + FSMNotFound(Uuid), + + /// Action could not be found. + ActionNotFound(Uuid), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use ErrorKind::*; + let msg = match &self.kind { + Serialization(err) => + format!("JSON serialization error: {}", err), + + Database(err) => + format!("PostgreSQL error: {}", err), + + DBPool(err) => + format!("Database connection pool error: {}", err), + + FSMNotFound(id) => + format!("FSM with ID {} not found", id), + + ActionNotFound(id) => + format!("Action with ID {} not found", id), + }; + + match &self.context { + None => write!(f, "{}", msg), + Some(ctx) => write!(f, "{}: {}", ctx, msg), + } + } +} + +impl StdError for Error {} + +impl <E: Into<ErrorKind>> From<E> for Error { + fn from(err: E) -> Error { + Error { + kind: err.into(), + context: None, + } + } +} + +impl From<JsonError> for ErrorKind { + fn from(err: JsonError) -> ErrorKind { + ErrorKind::Serialization(err.to_string()) + } +} + +impl From<PgError> for ErrorKind { + fn from(err: PgError) -> ErrorKind { + ErrorKind::Database(err.to_string()) + } +} + +impl From<PoolError> for ErrorKind { + fn from(err: PoolError) -> ErrorKind { + ErrorKind::DBPool(err.to_string()) + } +} + +/// Helper trait that makes it possible to supply contextual +/// information with an error. +pub trait ResultExt<T> { + fn context<C: fmt::Display>(self, ctx: C) -> Result<T>; +} + +impl <T, E: Into<Error>> ResultExt<T> for result::Result<T, E> { + fn context<C: fmt::Display>(self, ctx: C) -> Result<T> { + self.map_err(|err| Error { + context: Some(format!("{}", ctx)), + .. err.into() + }) + } +} |