pub struct OutboxService<W, S, P>{ /* private fields */ }Expand description
Producer-side facade for writing outbox events.
The service is generic over:
W—OutboxWriterimplementation (persists the event row)S—IdempotencyStorageProviderimplementation used to reserve tokens; set toNoIdempotencywhen no external reservation is neededP— the user’s domain event payload type (Debug + Clone + Serialize)
Construct with new when events should be written without an
external idempotency check, or with
with_idempotency to wire a reservation backend.
Implementations§
Source§impl<W, P> OutboxService<W, NoIdempotency, P>
impl<W, P> OutboxService<W, NoIdempotency, P>
Sourcepub fn new(writer: Arc<W>, config: Arc<OutboxConfig<P>>) -> Self
pub fn new(writer: Arc<W>, config: Arc<OutboxConfig<P>>) -> Self
Creates a service without any external idempotency reservation.
Tokens are still produced according to config.idempotency_strategy
and written alongside the event, so downstream consumers can deduplicate
on their side, but no pre-insert uniqueness check is performed here.
Use with_idempotency to attach a
reservation store (for example Redis) when at-producer deduplication
is required.
Source§impl<W, S, P> OutboxService<W, S, P>
impl<W, S, P> OutboxService<W, S, P>
Sourcepub fn with_idempotency(
writer: Arc<W>,
config: Arc<OutboxConfig<P>>,
idempotency_storage: Arc<S>,
) -> Self
pub fn with_idempotency( writer: Arc<W>, config: Arc<OutboxConfig<P>>, idempotency_storage: Arc<S>, ) -> Self
Creates a service wired to an external idempotency reservation store.
Before inserting the event, the service calls
IdempotencyStorageProvider::try_reserve with the token produced by
the configured strategy. If the reservation returns false, the insert
is skipped and OutboxError::DuplicateEvent is propagated to the
caller.
Sourcepub async fn add_event(
&self,
event_type: &str,
payload: P,
provided_token: Option<String>,
executor: W::Executor<'_>,
) -> Result<(), OutboxError>
pub async fn add_event( &self, event_type: &str, payload: P, provided_token: Option<String>, executor: W::Executor<'_>, ) -> Result<(), OutboxError>
Adds a new event to the outbox storage with idempotency checks.
The token is derived from
IdempotencyStrategy on the
configured OutboxConfig:
Provided— usesprovided_tokenas-is (Noneskips reservation).Uuid— generates a fresh UUID v7;provided_tokenis ignored.Custom(callback)— passes the event about to be written to the callback and uses the returnedStringas the token.None— no token is produced and reservation is skipped.
If an idempotency provider is configured and a token was produced, it will first attempt to reserve the token to prevent duplicate processing.
§Errors
Returns OutboxError::DuplicateEvent if the event token has already
been used. Returns any OutboxError variant propagated from the
reservation call or from the writer’s insert_event.
§Transactional usage
The executor argument is forwarded to the configured
OutboxWriter — for sqlx-based backends
this is typically &mut *tx borrowed from a held sqlx::Transaction.
Threading the transaction through the call is what makes the outbox
write atomic with the caller’s business write: both rows commit or
roll back together.
§Example
use std::sync::Arc;
use outbox_core::prelude::*;
service.add_event("order.created", payload, None, &mut *tx).await?;Auto Trait Implementations§
impl<W, S, P> !RefUnwindSafe for OutboxService<W, S, P>
impl<W, S, P> !UnwindSafe for OutboxService<W, S, P>
impl<W, S, P> Freeze for OutboxService<W, S, P>
impl<W, S, P> Send for OutboxService<W, S, P>
impl<W, S, P> Sync for OutboxService<W, S, P>
impl<W, S, P> Unpin for OutboxService<W, S, P>
impl<W, S, P> UnsafeUnpin for OutboxService<W, S, P>
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