#[non_exhaustive]pub enum PostgresOutboxError {
SchemaNotOnSearchPath {
configured: String,
observed: String,
},
NotMigrated {
schema: String,
},
SchemaOutOfDate {
schema: String,
missing: &'static str,
},
Database {
source: Error,
},
Decode {
id: OutboxRecordId,
message_id: MessageId,
detail: String,
},
UnknownMetadataVersion {
id: OutboxRecordId,
message_id: MessageId,
version: i32,
},
DuplicateMessage {
id: MessageId,
},
InvalidSchema {
schema: String,
},
UnsupportedServerVersion {
required: u32,
detected: u32,
},
}Expand description
A failure of a crate::PostgresOutboxStore OutboxStore/OutboxDeadLetters call —
never a property of one row’s content. Row-content problems surface as
reliar_outbox::PoisonedRows instead (ADR 0008).
Classify tells a dispatcher whether a failed call is worth retrying. The bare
PostgresOutboxStore below leans on its default type parameter, gated on the default
json feature; without it this block still shows the shape but is not compiled.
use reliar_core::Classify;
use reliar_outbox::{AcquireRequest, OutboxStore, WorkerId};
let request = AcquireRequest::new(WorkerId::generate());
if let Err(err) = store.acquire(request).await {
eprintln!("acquire failed ({:?}): {err}", err.kind());
}Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
SchemaNotOnSearchPath
The unqualified name outbox does not resolve, or resolves to a different schema than
configured. Carries the configured schema and the observed search_path; the ALTER ROLE remedy is in the Display text. Permanent.
Fields
NotMigrated
outbox resolved to the configured schema, but the relation itself is missing —
migrate() has not been run. Permanent. Mapped from SQLSTATE 42P01 on every
path, not just startup verification.
SchemaOutOfDate
outbox resolved to the configured schema and the relation exists, but it has not
finished a required migration — missing names the first column that is either absent or
present but still nullable (a completion marker, not a bare inventory check: id
exists from migration 0005 onward but stays nullable until 0010’s SET NOT NULL, so a
schema stuck anywhere in 0005–0009 is reported the same as one stuck at 0004).
Checked at crate::PostgresOutboxStore::connect, after the search_path
verification above and only once the relation is confirmed to exist there: a wrong
search_path or a missing relation each already has its own variant, so this one means
specifically “the right table, an old shape” (ADR 0044 Amendment A.4, marker corrected by
Amendment A.5) — today, message_id or id (migrations 0005–0010). The remedy is
migrate(&pool, ..), never a search_path fix. Permanent — the column will not
satisfy itself.
Fields
Database
Connection lost, statement timeout, pool exhausted, deadlock, or any other sqlx
failure not mapped to a more specific variant above. Classified by the wrapped
SQLSTATE’s class (never blanket-transient — see the Classify impl below).
Decode
A claimed or listed row could not be turned into an OutboxRecord (a corrupt JSONB
remainder, an unparseable promoted column). Surfaces as a poisoned row, never as an
acquire/list_dead failure. Permanent — the bytes on disk do not change between
attempts. Carries both ids (ADR 0044 A.2) — id and message_id are plain uuid columns
and are always readable even when the envelope columns that failed to decode are not.
Fields
id: OutboxRecordIdThe row’s own identity.
UnknownMetadataVersion
The row’s metadata_version is not one this build knows how to read. Permanent —
it needs a newer reader, not another try. Carries both ids, see Self::Decode.
Fields
id: OutboxRecordIdThe row’s own identity.
DuplicateMessage
enqueue inserted a MessageId that already exists (ix_outbox_message_id violation,
ADR 0044 §1). Permanent — a reused id never succeeds on retry; the row is already
there. Unlike Self::Decode/Self::UnknownMetadataVersion this carries only the
message id: the caller already knows it, and the row it collided with is not this call’s
concern (ADR 0044 A.2 — a pk_outbox collision, a record-id repeat, is a different,
non-caller error and stays Database).
InvalidSchema
PostgresOutboxSettings::schema or MigrateOptions::schema is not a valid PostgreSQL
identifier ([a-z_][a-z0-9_$]*, at most 63 bytes, lowercase only) — checked once,
before it is ever interpolated into SET search_path/dangerous_set_table_name.
Lowercase-only rather than merely case-insensitive: PostgreSQL folds an
unquoted identifier to lowercase, so an uppercase configured name and the schema it
actually resolves to would silently disagree unless every one of migrate()’s,
this crate’s own schema check’s and the host’s own search_path configuration happened to
quote it the same way everywhere — rejecting it up front removes the whole class of
mismatch. Permanent — configuration, not weather.
UnsupportedServerVersion
The connected server’s server_version_num is below crate::MIN_SERVER_VERSION_NUM
(PostgreSQL 18, ADR 0041) — no older-version fallback. Checked
at crate::PostgresOutboxStore::connect, before the search_path verification
above: a wrong server version explains a missing relation, and the reverse is never
true. Carries no connection string, host, or credentials. Permanent.
Fields
required: u32crate::MIN_SERVER_VERSION_NUM, restated on the value so this variant is
self-describing without a second lookup.
Trait Implementations§
Source§impl Classify for PostgresOutboxError
Per-variant classification table — no blanket “everything else is
transient”. A wrong verdict is not cosmetic: Transient burns the dispatcher’s retry
budget on a failure that can never succeed; Permanent kills a message that would have gone
through on the next attempt.
impl Classify for PostgresOutboxError
Per-variant classification table — no blanket “everything else is
transient”. A wrong verdict is not cosmetic: Transient burns the dispatcher’s retry
budget on a failure that can never succeed; Permanent kills a message that would have gone
through on the next attempt.
Source§fn kind(&self) -> FailureKind
fn kind(&self) -> FailureKind
Source§impl Debug for PostgresOutboxError
impl Debug for PostgresOutboxError
Source§impl Display for PostgresOutboxError
impl Display for PostgresOutboxError
Source§impl Error for PostgresOutboxError
impl Error for PostgresOutboxError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Auto Trait Implementations§
impl !RefUnwindSafe for PostgresOutboxError
impl !UnwindSafe for PostgresOutboxError
impl Freeze for PostgresOutboxError
impl Send for PostgresOutboxError
impl Sync for PostgresOutboxError
impl Unpin for PostgresOutboxError
impl UnsafeUnpin for PostgresOutboxError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more