下面显示的是英文原文。
Errors
SqsError is the crate's one error type: configuration, queues, receives, publishes, SNS admin, queue access policies, a closed connection and refused settings.
Each variant names the step that failed and the queue or topic it was about.
The SDK's failure behind it is its source, formatted with its whole cause chain, so the SDK's error types stay out of the crate's API.
| Variant | When |
|---|---|
Config | the in-process mode was asked of a broker whose handles already connected to AWS |
Queue | a queue could not be resolved, created, read or given its redrive policy |
Receive | a receive from an open subscription failed |
Publish | SQS refused a message, or SNS refused a notification |
Admin | a topic could not be created or a queue subscribed to it (sns feature) |
QueuePolicy | a queue's access policy could not be read or written while subscribe_queue_to_topic granted a topic the right to send to it (sns feature) |
NotConnected | a publisher was used before the broker connected, or after it shut down |
InvalidQueue | a descriptor is out of range: an empty name, a wait or a visibility SQS does not allow |
IncompleteRedrive | a registration declared max_attempts without dead_letter, or the other way round (dead letters) |
NotFifo | a publish named a group id or a deduplication id for a standard queue or topic |
A service meets the error in two places.
A failed startup carries it in the cause chain of the runtime's error, and the service exits before it reads anything.
A publish from a handler returns it as the source of the core's PublishError, and the handler decides how the delivery settles.
The enum is #[non_exhaustive], so a match on it ends with a wildcard arm.
Example
A shipment to a warehouse queue that is not FIFO is refused with NotFifo.
A retry would be refused again, so the handler drops the order and logs the error; any other failure is retried.
- Macros
- Manual
/// Whether SQS refused a publish because its destination is not a FIFO queue. The `SqsError` is
/// the source of the publish error, or a source further down its chain.
fn not_fifo(err: &(dyn Error + 'static)) -> bool {
let mut cause = Some(err);
while let Some(err) = cause {
if let Some(SqsError::NotFifo { .. }) = err.downcast_ref::<SqsError>() {
return true;
}
cause = err.source();
}
false
}
/// Ships an order through its warehouse's FIFO queue, in the customer's message group.
#[subscriber(SqsQueue::new("orders"))]
async fn ship(
order: &Order,
Out(shipments): Out<impl Publisher<Options = SqsPublishOptions>, Shipments>,
) -> HandlerOutcome {
let shipment = Shipment { order_id: order.id };
let sent = shipments
.message(&shipment)
.to(order.warehouse.as_str())
.group_id(&order.customer)
.publish()
.await;
match sent {
Ok(()) => HandlerOutcome::ack(),
// A standard queue has no message groups, and a retry would be refused again.
Err(err) if not_fifo(&err) => {
tracing::error!(subscription = "orders", order.id, error = %err, "not a FIFO queue");
HandlerOutcome::drop()
}
Err(err) => {
tracing::warn!(subscription = "orders", order.id, error = %err, "shipment not sent");
HandlerOutcome::retry()
}
}
}
/// Whether SQS refused a publish because its destination is not a FIFO queue. The `SqsError` is
/// the source of the publish error, or a source further down its chain.
fn not_fifo(err: &(dyn Error + 'static)) -> bool {
let mut cause = Some(err);
while let Some(err) = cause {
if let Some(SqsError::NotFifo { .. }) = err.downcast_ref::<SqsError>() {
return true;
}
cause = err.source();
}
false
}
/// Ships an order through its warehouse's FIFO queue, in the customer's message group.
struct Ship;
impl<Entry> Handle<Order, (), Outs<(Entry,)>> for Ship
where
Entry: OutEntry<Shipments, Wire: Publisher<Options = SqsPublishOptions>>,
{
async fn handle(
&self,
order: &Order,
outs: &Outs<(Entry,)>,
_ctx: &mut Context<'_>,
) -> Result<(), HandlerOutcome> {
let shipment = Shipment { order_id: order.id };
let sent = outs
.get(Shipments)
.message(&shipment)
.to(order.warehouse.as_str())
.group_id(&order.customer)
.publish()
.await;
match sent {
Ok(()) => Ok(()),
// A standard queue has no message groups, and a retry would be refused again.
Err(err) if not_fifo(&err) => {
tracing::error!(subscription = "orders", order.id, error = %err, "not a FIFO queue");
Err(HandlerOutcome::drop())
}
Err(err) => {
tracing::warn!(subscription = "orders", order.id, error = %err, "shipment not sent");
Err(HandlerOutcome::retry())
}
}
}
}