#![allow(async_fn_in_trait)]
use core::time::Duration;
use async_nats::HeaderMap;
use thiserror::Error;
use web_time::SystemTime;
use crate::bus::Wire;
pub trait AckHandle: Send + 'static {
async fn ack(self) -> anyhow::Result<()>;
async fn nak(self, delay: Option<Duration>) -> anyhow::Result<()>;
fn sequence(&self) -> u64;
fn deliveries(&self) -> u32;
}
pub struct Delivery<T, H: AckHandle> {
pub item: T,
pub handle: H,
pub subject: String,
pub msg_id: Option<String>,
pub headers: HeaderMap,
pub sent_at: Option<SystemTime>,
pub redelivered: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PublishOutcome {
Acked {
sequence: u64,
duplicate: bool,
},
}
#[derive(Debug, Error)]
pub enum PublishError {
#[error("ambiguous publish (may or may not have landed): {0}")]
Ambiguous(anyhow::Error),
#[error("publish failed: {0}")]
Failed(anyhow::Error),
}
impl PublishError {
#[must_use]
pub fn is_ambiguous(&self) -> bool {
matches!(self, PublishError::Ambiguous(_))
}
}
pub trait Publisher<T: Wire>: Clone + Send + Sync + 'static {
async fn publish_bytes(
&self,
subject: &str,
msg_id: &str,
headers: HeaderMap,
bytes: &[u8],
) -> Result<PublishOutcome, PublishError>;
async fn publish(
&self,
subject: &str,
msg_id: &str,
headers: HeaderMap,
item: &T,
) -> Result<PublishOutcome, PublishError> {
let bytes = item.encode().map_err(PublishError::Failed)?;
self.publish_bytes(subject, msg_id, headers, &bytes).await
}
}
pub trait Source<T: Wire>: Send {
type Handle: AckHandle;
async fn next(&mut self) -> Option<anyhow::Result<Delivery<T, Self::Handle>>>;
}
pub trait Consumer<T: Wire>: Send {
type Handle: AckHandle;
async fn fetch(
&mut self,
max: usize,
wait: Duration,
) -> anyhow::Result<Vec<Delivery<T, Self::Handle>>>;
}