本页尚未翻译
下面显示的是英文原文。
Dead letters
dead_letter names the stream key a spent delivery is written to, with its payload, its headers and its delivery count.
dead_letter(key) goes beside max_attempts(n).
The delivery that reaches the cap is published under that key instead of coming back.
It keeps its payload and the headers it arrived with, and its retry count says how many deliveries the message got.
On a stream file the key is one more stream inside the same file.
On a pipe it is a line under that key, which a downstream stage reads.
A service reads the dead letters with a subscription of their own, or a replay when an operator inspects them.
Example
A label that fails three times is written under labels.dead.
- Macros
- Manual
/// Prints a parcel label; the printer is jammed, so every attempt asks for another.
#[subscriber(FileStream::new("labels"))]
async fn print(label: &Label) -> HandlerOutcome {
tracing::info!(label.parcel, "printer jammed");
HandlerOutcome::retry_after(RETRY_DELAY)
}
#[ruststream::app]
fn app() -> impl App {
RustStream::new(AppInfo::new("labels", "0.1.0")).with_broker(
FileBroker::new("/var/lib/shop/labels.ss"),
|b| {
b.include(print)
.max_attempts(nonzero!(3u32))
.dead_letter("labels.dead");
},
)
}
/// Prints a parcel label; the printer is jammed, so every attempt asks for another.
struct Print;
impl Handle<Label> for Print {
fn handle(
&self,
label: &Label,
_outs: &(),
_ctx: &mut Context<'_>,
) -> impl Future<Output = Result<(), HandlerOutcome>> {
tracing::info!(label.parcel, "printer jammed");
ready(Err(HandlerOutcome::retry_after(RETRY_DELAY)))
}
}
fn app() -> impl App<State = ()> {
RustStream::new(AppInfo::new("labels", "0.1.0")).with_broker(
FileBroker::new("/var/lib/shop/labels.ss"),
|b| {
b.include(subscriber(FileStream::new("labels"), Print).build())
.max_attempts(nonzero!(3u32))
.dead_letter("labels.dead");
},
)
}