use sqlx::sqlite::SqlitePool; use crate::{ events::app::Broadcaster, repo::channel::{Channel, Provider as _}, }; pub struct Channels<'a> { db: &'a SqlitePool, broadcaster: &'a Broadcaster, } impl<'a> Channels<'a> { pub const fn new(db: &'a SqlitePool, broadcaster: &'a Broadcaster) -> Self { Self { db, broadcaster } } pub async fn create(&self, name: &str) -> Result { let mut tx = self.db.begin().await?; let channel = tx .channels() .create(name) .await .map_err(|err| CreateError::from_duplicate_name(err, name))?; self.broadcaster.register_channel(&channel.id); tx.commit().await?; Ok(channel) } pub async fn all(&self) -> Result, InternalError> { let mut tx = self.db.begin().await?; let channels = tx.channels().all().await?; tx.commit().await?; Ok(channels) } } #[derive(Debug, thiserror::Error)] pub enum CreateError { #[error("channel named {0} already exists")] DuplicateName(String), #[error(transparent)] DatabaseError(#[from] sqlx::Error), } impl CreateError { fn from_duplicate_name(error: sqlx::Error, name: &str) -> Self { if let Some(error) = error.as_database_error() { if error.is_unique_violation() { return Self::DuplicateName(name.into()); } } Self::from(error) } } #[derive(Debug, thiserror::Error)] pub enum InternalError { #[error(transparent)] DatabaseError(#[from] sqlx::Error), }