use std::future::Future;
use std::pin::Pin;
use crate::bus::{AsyncMessagePublisher, Message};
use crate::outbox::{OutboxMessage, OutboxPublishHook};
use crate::repository::RepositoryError;
use super::{AsyncOutboxStore, OutboxClaimRef};
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: AsyncOutboxStore,
P: AsyncMessagePublisher,
{
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_async(&claim).await,
Err(error) => self
.store
.record_failure_async(&claim, &error.to_string(), self.max_attempts)
.await
.map(|_action| ()),
}
})
}
}