下面显示的是英文原文。
At most once
Core NATS stores nothing and acknowledges nothing, so a Core delivery is processed at most once and a retry delivers nothing again.
The server hands a Core message to the subscribers connected at that moment and keeps no copy.
So settling a delivery of a CoreSubject or a CoreWildcard reports AckError::Unsupported, and the runtime logs it as a warning naming the subscription.
The handler's answer still decides what the framework does next.
ack and drop end the delivery.
A plain retry ends it too: the server has nothing to deliver again, and a message the handler could not process is gone.
retry_after, or any retry under a cap, makes the framework publish a copy of the message back to the subject, so the message comes back once.
That copy waits in the service's memory, so a process that exits before the delay is over loses it.
A message that has to survive a failed handler or a restart is read from a stream through a JetStreamSubject, which settles on the server.
Example
A shipping notice whose mail server does not answer asks for a retry, and the message is not delivered again.
- Macros
- Manual
/// Mails the customer once the order ships. A Core NATS message reaches whoever is subscribed
/// at that moment and is not stored, so `retry` here delivers nothing again: the message is
/// processed at most once.
#[subscriber("orders.shipped")]
async fn notify(order: &Shipped) -> HandlerOutcome {
match send_mail(&order.email).await {
Ok(()) => HandlerOutcome::ack(),
Err(err) => {
tracing::error!(order.id, %err, "the shipping notice is lost");
HandlerOutcome::retry()
}
}
}
/// Mails the customer once the order ships. A Core NATS message reaches whoever is subscribed
/// at that moment and is not stored, so `Err(retry)` here delivers nothing again: the message is
/// processed at most once.
struct Notify;
impl Handle<Shipped> for Notify {
async fn handle(
&self,
order: &Shipped,
_outs: &(),
_ctx: &mut Context<'_>,
) -> Result<(), HandlerOutcome> {
send_mail(&order.email).await.map_err(|err| {
tracing::error!(order.id, %err, "the shipping notice is lost");
HandlerOutcome::retry()
})
}
}