use core::fmt;
use reliar_core::{Classify, FailureKind, MessageId};
use crate::error::{classify_sqlstate, is_undefined_table};
#[derive(Debug)]
#[non_exhaustive]
pub enum PostgresInboxError {
NotMigrated {
source: sqlx::Error,
},
NotClaimed {
scope: String,
message_id: MessageId,
},
InvalidSettings {
message: String,
},
Database {
source: sqlx::Error,
},
}
impl fmt::Display for PostgresInboxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotMigrated { source } => write!(
f,
"the inbox table does not resolve on this connection's search_path: {source}; \
run reliar_store_postgres::migrate(&pool, ..) and put the migrated schema first \
on search_path — in the connection URL \
(options=-c search_path=reliar,public) or with ALTER ROLE <role> SET \
search_path = reliar, public"
),
Self::NotClaimed { scope, message_id } => write!(
f,
"no claimed inbox row for scope {scope:?}, message {message_id}; complete() may \
only follow a Claimed claim() in the same transaction, and never a dead one"
),
Self::InvalidSettings { message } => {
write!(f, "invalid PostgresInboxSettings: {message}")
}
Self::Database { source } => write!(f, "database error: {source}"),
}
}
}
impl std::error::Error for PostgresInboxError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::NotMigrated { source } | Self::Database { source } => Some(source),
Self::NotClaimed { .. } | Self::InvalidSettings { .. } => None,
}
}
}
impl Classify for PostgresInboxError {
fn kind(&self) -> FailureKind {
match self {
Self::NotMigrated { .. } | Self::NotClaimed { .. } | Self::InvalidSettings { .. } => {
FailureKind::Permanent
}
Self::Database { source } => classify_sqlstate(source),
}
}
}
impl From<sqlx::Error> for PostgresInboxError {
fn from(source: sqlx::Error) -> Self {
map_operational_error(source)
}
}
pub(crate) fn map_operational_error(err: sqlx::Error) -> PostgresInboxError {
if is_undefined_table(&err) {
return PostgresInboxError::NotMigrated { source: err };
}
PostgresInboxError::Database { source: err }
}
impl crate::error::FromDatabaseError for PostgresInboxError {
fn from_database_error(err: sqlx::Error) -> Self {
map_operational_error(err)
}
}