Ниже показан английский оригинал.
Outcomes
Each outcome is one SQS call: ack and drop delete the message, retry makes it visible again at once.
ack deletes the message with DeleteMessage.
drop deletes it too, because SQS has no call that rejects a message without deleting it.
retry sets the message's visibility timeout to zero, so the next receive hands it out again.
retry_after sets the timeout to a delay instead.
A redelivered message is the same message: the queue counts its receives, and the handler reads the count in RECEIVE_COUNT_HEADER.
A delivery the service never settles, as when its process stops, makes no call, and the message comes back once its visibility timeout lapses.
A redrive policy caps the receives, and the queue moves a spent message to a dead-letter queue itself.
In the manual form Ok(()) acknowledges the delivery and Err(outcome) settles it with that outcome.
Example
A malformed payment is dropped, a payment the gateway was too busy for comes back at once, and a charged one is deleted.
- Macros
- Manual
/// One payment per delivery. A malformed payment is dropped, a busy gateway gets the payment
/// again at once, and a charged payment is acknowledged.
#[subscriber(SqsQueue::new("payments"))]
async fn charge(payment: &Payment, cx: &mut Context<'_>) -> HandlerOutcome {
if payment.amount_cents <= 0 {
tracing::warn!(payment.id, "malformed payment dropped");
// DeleteMessage: the payment never comes back.
return HandlerOutcome::drop();
}
let attempt = cx.headers().get_str(RECEIVE_COUNT_HEADER).unwrap_or("1");
if charge_card(payment, attempt).await.is_err() {
tracing::warn!(payment.id, attempt, "gateway busy");
// ChangeMessageVisibility to zero: the next receive hands it out again.
return HandlerOutcome::retry();
}
// DeleteMessage.
HandlerOutcome::ack()
}
/// One payment per delivery. A malformed payment is dropped, a busy gateway gets the payment
/// again at once, and a charged payment is acknowledged.
struct Charge;
impl Handle<Payment> for Charge {
async fn handle(
&self,
payment: &Payment,
_outs: &(),
ctx: &mut Context<'_>,
) -> Result<(), HandlerOutcome> {
if payment.amount_cents <= 0 {
tracing::warn!(payment.id, "malformed payment dropped");
// DeleteMessage: the payment never comes back.
return Err(HandlerOutcome::drop());
}
let attempt = ctx.headers().get_str(RECEIVE_COUNT_HEADER).unwrap_or("1");
if charge_card(payment, attempt).await.is_err() {
tracing::warn!(payment.id, attempt, "gateway busy");
// ChangeMessageVisibility to zero: the next receive hands it out again.
return Err(HandlerOutcome::retry());
}
// DeleteMessage.
Ok(())
}
}