use std::sync::Arc;
use super::error::Error;
use super::publish::Publish;
use crate::config::RabbitMq;
use lapin::{
options::BasicPublishOptions, publisher_confirm::Confirmation, types::FieldTable,
BasicProperties, Channel, Connection, ConnectionProperties,
};
use mongodb::{bson::Document, change_stream::event::ChangeStreamEvent};
use serde_json;
use tracing::trace;
pub struct Publisher {
pub config: RabbitMq,
channel: Channel,
_connection: Arc<Connection>,
}
impl Publisher {
pub async fn new(config: &RabbitMq, rabbitmq_uri: &str) -> Result<Self, Error> {
let conn = Connection::connect(rabbitmq_uri, ConnectionProperties::default()).await?;
let channel = conn.create_channel().await?;
channel
.queue_declare(
&config.stream_name,
Default::default(),
FieldTable::default(),
)
.await?;
Ok(Self {
config: config.clone(),
channel,
_connection: Arc::new(conn),
})
}
pub async fn with_connection(
config: RabbitMq,
connection: Arc<Connection>,
) -> Result<Self, Error> {
let channel = connection.create_channel().await?;
channel
.queue_declare(
&config.stream_name,
Default::default(),
FieldTable::default(),
)
.await?;
Ok(Self {
config,
channel,
_connection: connection,
})
}
pub async fn publish(&self, event: &ChangeStreamEvent<Document>) -> Result<(), Error> {
let payload = serde_json::to_vec(event)?;
let confirm: Confirmation = self
.channel
.basic_publish(
"",
&self.config.stream_name,
BasicPublishOptions::default(),
&payload,
BasicProperties::default(),
)
.await?
.await?;
trace!(queue = %self.config.stream_name, "Published message to RabbitMQ, payload: {}, confirmation: {:?}", serde_json::to_string(event)?, confirm);
Ok(())
}
}
#[async_trait::async_trait]
impl Publish for Publisher {
async fn publish(&self, event: &ChangeStreamEvent<Document>) -> Result<(), Error> {
self.publish(event).await
}
}