use std::future::Future;
use std::pin::Pin;
use crate::bus::{Message, MessagePublisher};
use crate::outbox::{OutboxMessage, OutboxPublishHook};
use crate::repository::RepositoryError;
use super::{OutboxClaimRef, OutboxStore};
pub struct BusOutboxPublishHook<S, P> {
store: S,
publisher: P,
max_attempts: u32,
}
impl<S, P> BusOutboxPublishHook<S, P> {
pub fn new(store: S, publisher: P, max_attempts: u32) -> Self {
Self {
store,
publisher,
max_attempts,
}
}
}
impl<S, P> OutboxPublishHook for BusOutboxPublishHook<S, P>
where
S: OutboxStore,
P: MessagePublisher,
{
fn publish_claimed<'a>(
&'a self,
claimed: OutboxMessage,
) -> Pin<Box<dyn Future<Output = Result<(), RepositoryError>> + Send + 'a>> {
Box::pin(async move {
let claim = OutboxClaimRef::from_message(&claimed)?;
let message = Message::from(&claimed);
match self.publisher.publish(message).await {
Ok(()) => self.store.complete(&claim).await,
Err(error) => self
.store
.record_failure(&claim, &error.to_string(), self.max_attempts)
.await
.map(|_action| ()),
}
})
}
}