use async_trait::async_trait;
use thiserror::Error;
use crate::runtime::AgentEvent;
pub type QueueResult<T> = Result<T, QueueError>;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum QueueError {
#[error("queue connection failed: {message}")]
ConnectionFailed {
message: String,
},
#[error("queue publish failed: {message}")]
PublishFailed {
message: String,
},
#[error("queue serialization failed: {message}")]
SerializationFailed {
message: String,
},
}
#[async_trait]
pub trait EventPublisher: Send + Sync {
async fn publish(&self, event: AgentEvent) -> QueueResult<()>;
}
#[cfg(feature = "nats")]
mod nats;
#[cfg(feature = "redis")]
mod redis_streams;
#[cfg(feature = "nats")]
pub use nats::NatsEventPublisher;
#[cfg(feature = "redis")]
pub use redis_streams::RedisStreamsPublisher;
pub struct NoOpPublisher;
impl NoOpPublisher {
#[must_use]
pub fn new() -> Self {
Self
}
}
impl Default for NoOpPublisher {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl EventPublisher for NoOpPublisher {
async fn publish(&self, _event: AgentEvent) -> QueueResult<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use uuid::Uuid;
use crate::runtime::RunId;
use crate::runtime::event::RunStarted;
#[tokio::test]
async fn no_op_publisher_should_accept_any_event() {
let publisher = NoOpPublisher::new();
let event = AgentEvent::RunStarted(RunStarted {
run_id: RunId::new(),
session_id: Uuid::new_v4(),
provider: crate::provider::ProviderId::new("test"),
model: crate::provider::ModelName::new("test"),
timestamp: chrono::Utc::now(),
});
let result = publisher.publish(event).await;
assert!(result.is_ok());
}
}