buster/api/src/routes/ws/threads_and_messages/delete_thread.rs

161 lines
5.0 KiB
Rust

use anyhow::{anyhow, Result};
use diesel::{update, ExpressionMethods};
use diesel_async::RunQueryDsl;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use uuid::Uuid;
use middleware::AuthenticatedUser;
use database::{pool::get_pg_pool,
schema::threads_deprecated,};
use crate::{
routes::ws::{
ws::{SubscriptionRwLock, WsErrorCode, WsEvent, WsResponseMessage, WsSendMethod},
ws_router::WsRoutes,
ws_utils::{send_error_message, send_ws_message},
},
utils::clients::sentry_utils::send_sentry_error,
};
use super::threads_router::{ThreadEvent, ThreadRoute};
#[derive(Deserialize, Debug, Clone)]
pub struct DeleteThreadRequest {
pub ids: Vec<Uuid>,
}
#[derive(Serialize, Debug, Clone)]
pub struct DeleteThreadRes {
pub id: Uuid,
}
pub async fn delete_thread(
subscriptions: &Arc<SubscriptionRwLock>,
user: &AuthenticatedUser,
req: DeleteThreadRequest,
) -> Result<()> {
let mut delete_tasks = Vec::new();
for id in req.ids {
let subscription = format!("thread:{}", id);
let delete_thread_res = match delete_thread_handler(user, &id).await {
Ok(res) => res,
Err(e) => {
tracing::error!("Error getting thread: {}", e);
send_sentry_error(&e.to_string(), None);
send_error_message(
&user.id.to_string(),
WsRoutes::Threads(ThreadRoute::Delete),
WsEvent::Threads(ThreadEvent::DeleteThreadState),
WsErrorCode::InternalServerError,
"Failed to delete thread.".to_string(),
user,
)
.await?;
return Err(anyhow!("Error getting thread: {}", e));
}
};
delete_tasks.push(delete_thread_res);
let delete_thread_res_message = WsResponseMessage::new(
WsRoutes::Threads(ThreadRoute::Delete),
WsEvent::Threads(ThreadEvent::DeleteThreadState),
vec![id],
None,
user,
WsSendMethod::All,
);
match send_ws_message(&subscription, &delete_thread_res_message).await {
Ok(_) => {}
Err(e) => {
tracing::error!("Error sending message to pubsub: {}", e);
let err = anyhow!("Error sending message to pubsub: {}", e);
send_sentry_error(&err.to_string(), Some(&user.id));
return Err(err);
}
}
subscriptions.remove(subscription.clone()).await;
}
let mut delete_responses = Vec::new();
for task in delete_tasks {
match task.await {
Ok(Ok(res)) => delete_responses.push(res.id),
Ok(Err(e)) => {
tracing::error!("Unable to insert thread into database: {:?}", e);
let err = anyhow!("Unable to insert thread into database: {}", e);
send_sentry_error(&err.to_string(), Some(&user.id));
return Err(err);
}
Err(e) => {
tracing::error!("Unable to insert thread into database: {:?}", e);
let err = anyhow!("Unable to insert thread into database: {}", e);
send_sentry_error(&err.to_string(), Some(&user.id));
return Err(err);
}
}
}
let delete_thread_res_message = WsResponseMessage::new(
WsRoutes::Threads(ThreadRoute::Delete),
WsEvent::Threads(ThreadEvent::DeleteThreadState),
delete_responses,
None,
user,
WsSendMethod::All,
);
match send_ws_message(&user.id.to_string(), &delete_thread_res_message).await {
Ok(_) => {}
Err(e) => {
tracing::error!("Error sending message to pubsub: {}", e);
let err = anyhow!("Error sending message to pubsub: {}", e);
send_sentry_error(&err.to_string(), Some(&user.id));
return Err(err);
}
}
Ok(())
}
async fn delete_thread_handler(
user: &AuthenticatedUser,
id: &Uuid,
) -> Result<tokio::task::JoinHandle<Result<DeleteThreadRes>>> {
let mut conn = get_pg_pool().get().await.map_err(|e| {
tracing::error!("Error getting connection from pool: {}", e);
let err = anyhow!("Error getting connection: {}", e);
send_sentry_error(&err.to_string(), Some(&user.id));
err
})?;
let id = id.clone();
let delete_thread_task = tokio::task::spawn(async move {
match update(threads_deprecated::table)
.filter(threads_deprecated::id.eq(&id))
.set(threads_deprecated::deleted_at.eq(chrono::Utc::now()))
.execute(&mut conn)
.await
{
Ok(_) => (),
Err(e) => {
tracing::error!("Unable to insert thread: {:?}", e);
let err = anyhow!("Unable to insert thread: {}", e);
send_sentry_error(&err.to_string(), None);
return Err(err);
}
}
Ok(DeleteThreadRes { id })
});
Ok(delete_thread_task)
}