use std::future::{Future, ready};
use ruststream::{OutgoingFor, OwnedTransactions, Take, Transaction};
use tracing::warn;
use crate::error::AmqpError;
use crate::publish_step::LapinPublishOptions;
use crate::publisher::{Buffered, ConfirmsPublisher};
#[must_use = "a transaction does nothing until settled with commit() or abort()"]
pub struct ConfirmsTransaction {
publisher: ConfirmsPublisher,
buffered: Vec<Buffered>,
settled: bool,
}
impl std::fmt::Debug for ConfirmsTransaction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ConfirmsTransaction")
.field("buffered", &self.buffered.len())
.field("settled", &self.settled)
.finish_non_exhaustive()
}
}
impl Drop for ConfirmsTransaction {
fn drop(&mut self) {
if !self.settled {
warn!(
target: "ruststream_lapin",
buffered = self.buffered.len(),
"owned transaction dropped without commit or abort; its buffered messages are \
discarded"
);
}
}
}
impl Transaction for ConfirmsTransaction {
type Payload = Take;
type Error = AmqpError;
type Options = LapinPublishOptions;
fn publish(
&mut self,
msg: OutgoingFor<'_, Take>,
options: Option<&Self::Options>,
) -> impl Future<Output = Result<(), Self::Error>> {
self.buffered.push(Buffered::taken(msg, options));
ready(Ok(()))
}
async fn commit(mut self) -> Result<(), Self::Error> {
self.settled = true;
self.publisher.flush_owned(&self.buffered).await
}
fn abort(mut self) -> impl Future<Output = Result<(), Self::Error>> {
self.settled = true;
ready(Ok(()))
}
}
impl OwnedTransactions for ConfirmsPublisher {
type Transaction = ConfirmsTransaction;
fn transaction(&self) -> impl Future<Output = Result<Self::Transaction, Self::Error>> {
ready(Ok(ConfirmsTransaction {
publisher: self.clone(),
buffered: Vec::new(),
settled: false,
}))
}
}