Skip to main content

runledger_postgres/
lib.rs

1//! PostgreSQL persistence layer for Runledger durable execution.
2//!
3//! This crate owns the SQLx-backed storage and query helpers used by the
4//! runtime and application crates. The main entrypoint is the [`jobs`] module,
5//! which exposes APIs for:
6//! - queueing, claiming, heartbeating, and completing jobs
7//! - listing admin/job log data and runtime configuration
8//! - enqueueing and querying workflow runs and steps
9//!
10//! Typical consumers share a [`DbPool`] with `runledger-runtime`, then call the
11//! exported [`jobs`] functions from application setup, admin APIs, or tests.
12//! This crate assumes the matching Runledger schema is already present in the
13//! target database.
14
15use std::fmt;
16
17mod error;
18pub mod jobs;
19
20pub use error::{
21    FrameworkConstraintSpec, QueryError, QueryErrorCategory, classify_framework_constraint,
22    classify_query_error, classify_query_error_with_constraint_classifier,
23    has_framework_constraint_classifier,
24};
25
26pub type DbPool = sqlx::PgPool;
27pub type DbTx<'a> = sqlx::Transaction<'a, sqlx::Postgres>;
28pub type Result<T> = std::result::Result<T, Error>;
29
30#[derive(Debug)]
31pub enum Error {
32    ConfigError(String),
33    ConnectionError(String),
34    MigrationError(String),
35    QueryError(QueryError),
36}
37
38impl fmt::Display for Error {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        match self {
41            Self::ConfigError(message) => write!(f, "{message}"),
42            Self::ConnectionError(message) => write!(f, "{message}"),
43            Self::MigrationError(message) => write!(f, "{message}"),
44            Self::QueryError(query_error) => write!(f, "{query_error}"),
45        }
46    }
47}
48
49impl std::error::Error for Error {
50    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
51        match self {
52            Self::QueryError(query_error) => Some(query_error),
53            Self::ConfigError(_) | Self::ConnectionError(_) | Self::MigrationError(_) => None,
54        }
55    }
56}
57
58impl Error {
59    #[must_use]
60    pub fn from_query_sqlx(error: sqlx::Error) -> Self {
61        Self::QueryError(QueryError::from_sqlx(error, None))
62    }
63
64    #[must_use]
65    pub fn from_query_sqlx_with_context(context: &str, error: sqlx::Error) -> Self {
66        Self::QueryError(QueryError::from_sqlx(error, Some(context)))
67    }
68}