strut_rabbitmq/transport/outbound/publisher/
api.rs

1use crate::transport::outbound::publisher::inner::{
2    NotConfirmed, NotTransmitted, PartlyConfirmedBatch,
3};
4use crate::Dispatch;
5use nonempty::NonEmpty;
6use std::fmt::{Display, Formatter};
7use thiserror::Error;
8
9/// Shorthand for a result of a single publishing attempt.
10pub type PublishingResult = Result<Dispatch, PublishingError>;
11
12/// Shorthand for a result of a batch publishing attempt.
13pub type BatchPublishingResult = Result<Vec<Dispatch>, BatchPublishingError>;
14
15/// Represents a failed publishing of a single RabbitMQ message.
16#[derive(Error, Debug)]
17#[error("failed to publish a RabbitMQ message: {failure}")]
18pub struct PublishingError {
19    /// The message that failed to get published.
20    pub dispatch: Dispatch,
21    /// The high-level explanation of the failure.
22    pub failure: PublishingFailure,
23}
24
25/// Represents a (partially) failed publishing of a batch of RabbitMQ messages.
26#[derive(Error, Debug)]
27#[error(
28    "failed to fully publish a batch of {} RabbitMQ messages: {} messages went through, {} messages did not go through",
29    published.len() + not_published.len(),
30    published.len(),
31    not_published.len(),
32)]
33pub struct BatchPublishingError {
34    /// The messages that went through (successfully published).
35    pub published: Vec<Dispatch>,
36    /// The messages that did not go through (failed to get published).
37    pub not_published: NonEmpty<PublishingError>,
38}
39
40/// Explains what exactly went wrong in publishing a single RabbitMQ message.
41#[derive(Debug)]
42pub enum PublishingFailure {
43    /// The message was not transmitted to the broker.
44    NotTransmitted,
45    /// The message was negatively acknowledged by the broker (not routed to an
46    /// exchange or a queue, depending on confirmation level).
47    NegativelyAcknowledged,
48    /// The broker suffered an internal error during acknowledgement of the
49    /// message.
50    BrokerError,
51    /// Failed to retrieve the acknowledgement from the broker.
52    CommunicationError,
53}
54
55impl Display for PublishingFailure {
56    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
57        match self {
58            PublishingFailure::NotTransmitted => {
59                f.write_str("the message was not transmitted to the broker")
60            }
61            PublishingFailure::NegativelyAcknowledged => f.write_str(concat!(
62                "the message was negatively acknowledged by the broker",
63                " (not routed to an exchange or a queue, depending on",
64                " confirmation level)",
65            )),
66            PublishingFailure::BrokerError => f.write_str(
67                "the broker suffered an internal error during acknowledgement of the message",
68            ),
69            PublishingFailure::CommunicationError => {
70                f.write_str("failed to retrieve the acknowledgement from the broker")
71            }
72        }
73    }
74}
75
76impl From<NotTransmitted> for PublishingError {
77    fn from(value: NotTransmitted) -> Self {
78        let dispatch = match value {
79            NotTransmitted::NotAttempted(dispatch) => dispatch,
80            NotTransmitted::TransmissionError(dispatch, _) => dispatch,
81        };
82
83        Self {
84            dispatch,
85            failure: PublishingFailure::NotTransmitted,
86        }
87    }
88}
89
90impl From<NotConfirmed> for PublishingError {
91    fn from(value: NotConfirmed) -> Self {
92        match value {
93            NotConfirmed::NotAttempted(dispatch) => Self {
94                dispatch,
95                failure: PublishingFailure::NotTransmitted,
96            },
97            NotConfirmed::TransmissionError(dispatch, _error) => Self {
98                dispatch,
99                failure: PublishingFailure::NotTransmitted,
100            },
101            NotConfirmed::Negative(dispatch, _return) => Self {
102                dispatch,
103                failure: PublishingFailure::NegativelyAcknowledged,
104            },
105            NotConfirmed::BrokerError(dispatch, _return) => Self {
106                dispatch,
107                failure: PublishingFailure::BrokerError,
108            },
109            NotConfirmed::ConfirmationError(dispatch, _error) => Self {
110                dispatch,
111                failure: PublishingFailure::CommunicationError,
112            },
113        }
114    }
115}
116
117impl From<PartlyConfirmedBatch> for BatchPublishingError {
118    fn from(value: PartlyConfirmedBatch) -> Self {
119        BatchPublishingError {
120            published: value
121                .confirmed_dispatches
122                .into_iter()
123                .map(Dispatch::from)
124                .collect(),
125            not_published: value.not_confirmed_dispatches.map(PublishingError::from),
126        }
127    }
128}