use config::AppConfig; use queue::{AckAction, MessageHandler, NatsConsumer}; use tracing::error; use crate::{EmailMessage, SmtpEmailSender}; pub struct EmailWorker { sender: SmtpEmailSender, } impl EmailWorker { pub fn new(sender: SmtpEmailSender) -> Self { Self { sender } } pub async fn start(config: &AppConfig) -> anyhow::Result<()> { let worker = Self::new(SmtpEmailSender::new(config)?); let consumer = NatsConsumer::new(config, &config.email_consumer_group_id()) .await?; let topic = config.email_topic(); consumer.start_consuming(&[topic.as_str()], worker).await?; std::future::pending().await } } #[async_trait::async_trait] impl MessageHandler for EmailWorker { async fn handle(&self, topic: &str, payload: &[u8]) -> AckAction { let message = match serde_json::from_slice::(payload) { Ok(message) => message, Err(error) => { error!(topic, error = %error, "invalid email message payload"); return AckAction::Ack; } }; match self.sender.send(message).await { Ok(()) => AckAction::Ack, Err(error) => { error!(topic, error = %error, "email message send failed"); AckAction::Nack } } } }