1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! `reliar-outbox` is the storage-agnostic transactional outbox: the [`OutboxStore`]/
//! [`OutboxDeadLetters`] capability traits (plus `reliar_core::Publisher`, re-exported here for
//! convenience), the request and result types that cross their boundary, a pure [`RetryPolicy`],
//! the feature's [`OutboxSettings`], and the [`OutboxMetrics`] hook (SRS §19–§26).
//!
//! This slice ships the traits and types a provider builds against, a host configures, the
//! [`OutboxDispatcher`] worker loop, and the `test-support` fakes a test drives without a
//! database.
//!
//! Enable the `test-support` feature for `InMemoryOutboxStore`, `RecordingPublisher`,
//! `ScriptedPublisher` and `RecordingMetrics` — one shared set of fakes reused by provider
//! crates, examples and `tests/system` (SRS §8.1, §43.A.27).
// Plain code spans above, not intra-doc links: those types only exist when `test-support` is
// enabled, and `cargo doc` on default features must not break trying to resolve a link to an
// item that is not compiled in.
//!
//! # Guarantees
//!
//! - **Durable at-least-once publication. Never exactly-once.** Duplicate delivery is expected
//! and must be handled by an idempotent consumer (SRS §22). Two distinct windows produce a
//! duplicate, and both are unavoidable:
//! 1. **The crash window** (§22): a publish reaches the broker, the worker crashes before
//! `complete` persists, the lease expires, and another worker republishes the same message.
//! 2. **The slow-batch window** (§22.1): no crash at all — a worker claims a large batch under
//! a lease shorter than the batch takes to drain, the lease expires while the worker is
//! still healthily publishing, a second worker reclaims and republishes the tail, and the
//! first worker's later `complete`/`fail` is rejected by the `locked_by` guard.
//! 3. **The drain window** (§26.1): on cancellation, `run()` drains in-flight publishes for at
//! most `DispatcherSettings::drain_timeout`; a publish still unresolved at the timeout is
//! released rather than awaited further, and its outcome — success or failure — is the same
//! duplicate risk as the other two windows, just triggered by shutdown instead of a lease.
//! - **No ordering by default.** [`Ordering::Unordered`] (the default) guarantees **nothing**
//! about order — not globally, not per `conversation_id`, not per aggregate, not
//! approximately. `SKIP LOCKED`, concurrent publishing, per-message backoff and multiple
//! workers each reorder freely (§22.2, ADR 0013). [`Ordering::PerKey`] is a configuration
//! error in this release — see [`Ordering::validate`].
//! - **Pure retry.** [`RetryPolicy`] is I/O-free and clock-free: it returns a [`core::time::Duration`],
//! never a timestamp. The store applies it as `available_at = now() + delay` in SQL, so a
//! worker's clock skew can never hot-loop a row or park it in the future (ADR 0009).
//! - **The library never reads the environment implicitly.** Only [`OutboxSettings::from_env`]
//! touches `std::env`, and only when called (ADR 0019).
pub use ;
pub use ConfigError;
pub use ;
pub use Ordering;
pub use ;
/// Re-exported from `reliar-core` (ADR 0032): a store author's or a publisher's `Classify`
/// bound, a publish/store failure's `FailureKind`, the `Publisher` capability trait, and the
/// shared `SettingsError` all live in core now. New code should name `reliar_core::` directly;
/// this re-export keeps existing `use reliar_outbox::{…}` imports one line.
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use WorkerId;