pub trait OutboxStorage<P>{
// Required methods
fn fetch_next_to_process<'life0, 'async_trait>(
&'life0 self,
limit: u32,
) -> Pin<Box<dyn Future<Output = Result<Vec<Event<P>>, OutboxError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn update_status<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 [EventId],
status: EventStatus,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn delete_garbage<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn wait_for_notification<'life0, 'life1, 'async_trait>(
&'life0 self,
channel: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided method
fn quarantine_events<'life0, 'life1, 'async_trait>(
&'life0 self,
_entries: &'life1 [DlqEntry],
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>
where Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
}Expand description
Worker-side storage contract.
An implementation must provide the read and lifecycle operations the
OutboxManager drives on every tick:
claiming pending rows, recording their outcome, cleaning up finished data,
and blocking until an external notification arrives.
Required Methods§
Sourcefn fetch_next_to_process<'life0, 'async_trait>(
&'life0 self,
limit: u32,
) -> Pin<Box<dyn Future<Output = Result<Vec<Event<P>>, OutboxError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn fetch_next_to_process<'life0, 'async_trait>(
&'life0 self,
limit: u32,
) -> Pin<Box<dyn Future<Output = Result<Vec<Event<P>>, OutboxError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Claims up to limit rows that are eligible for processing.
“Eligible” means rows whose status is
EventStatus::Pending — including
newly inserted rows and rows whose processing lock has expired.
Implementations are expected to atomically flip the returned rows to
EventStatus::Processing
with a lock that expires after lock_timeout_mins, so concurrent
workers cannot pick up the same row.
§Errors
Returns an OutboxError if the underlying datastore call fails.
Sourcefn update_status<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 [EventId],
status: EventStatus,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn update_status<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 [EventId],
status: EventStatus,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Transitions the rows identified by id to status.
Typically called after a batch publish attempt:
EventStatus::Sent for successful
publications, or
EventStatus::Pending to release
a row for retry.
§Errors
Returns an OutboxError if the underlying datastore call fails.
Sourcefn delete_garbage<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn delete_garbage<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Deletes rows that are past their retention window.
Invoked on a timer by the GarbageCollector
task. The retention window itself is defined by the storage
implementation (it usually reads retention_days from the same
configuration the manager holds).
§Errors
Returns an OutboxError if the underlying datastore call fails.
Sourcefn wait_for_notification<'life0, 'life1, 'async_trait>(
&'life0 self,
channel: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn wait_for_notification<'life0, 'life1, 'async_trait>(
&'life0 self,
channel: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Blocks until a notification arrives on channel, or returns
immediately on the next call if the backend does not support async
notifications.
Used by the manager’s wake-up loop in combination with a poll interval: the backend can deliver a nudge as soon as a new row is written, while the poll interval guarantees eventual progress if the notification is missed.
§Errors
Returns an OutboxError if the listen call fails. The manager
recovers by logging and sleeping 5 seconds before retrying.
Provided Methods§
Sourcefn quarantine_events<'life0, 'life1, 'async_trait>(
&'life0 self,
_entries: &'life1 [DlqEntry],
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn quarantine_events<'life0, 'life1, 'async_trait>(
&'life0 self,
_entries: &'life1 [DlqEntry],
) -> Pin<Box<dyn Future<Output = Result<(), OutboxError>> + Send + 'async_trait>>where
Self: Sync + 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Atomically moves the given entries out of the active outbox table and into the dead-letter destination table.
Called once per tick by
DlqProcessor after
DlqHeap::drain_exceeded
has returned a non-empty batch. The whole entries slice is expected
to be moved in a single transaction so there is no observable window
in which a row appears in neither table or in both.
entries carries failure_count (and any future per-event metadata)
alongside each EventId; the implementation persists those values
onto the destination row.
Ids in entries whose source row no longer exists (already deleted
by GC, manual operator action, etc.) are silently dropped — only
matched rows are moved.
§Default implementation
The default implementation returns an OutboxError::ConfigError.
Backend crates ship a real implementation behind their own dlq
feature; this default is what callers see when the backend was built
without DLQ support but outbox-core/dlq happens to be enabled
elsewhere in the workspace (Cargo’s feature unification can pull it
in transitively).
The method is intentionally not #[cfg(feature = "dlq")]-gated:
gating it on the trait creates a workspace-level mismatch where
outbox-core sees the method (because some other crate enabled the
feature) but a backend crate built without its own dlq feature
does not provide an implementation.
§Errors
Returns an OutboxError if the underlying datastore call fails.
On error, the caller should assume none of the entries were
moved — implementations must not partially commit.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".