Removing passthrough for message send handler

This means we get more opaque errors for the clients but it also results in way less code to maintain
This commit is contained in:
shockrah 2021-03-30 21:39:44 -07:00
parent d88948385d
commit 15b56353b8

View File

@ -4,15 +4,12 @@ use tokio::fs;
use tokio::io::AsyncWriteExt;
use mysql_async::params;
use mysql_async::{Pool, Conn};
use mysql_async::Pool;
use mysql_async::prelude::Queryable;
use mysql_async::error::Error as SqlError;
use mysql_async::QueryResult;
use mysql_async::BinaryProtocol;
use mysql_async::Error as SqlError;
use crate::{Response, sql_err};
use crate::{UBigInt, BigInt, VarChar};
use crate::Response;
use crate::{UBigInt, BigInt};
use crate::{Message, UserMessage};
use rand::RngCore;
@ -33,42 +30,12 @@ impl Message {
}
}
fn message_passthrough_no_err(res: Result<QueryResult<Conn, BinaryProtocol>, SqlError>, passthrough: Self)
-> Result<Response<Self>, SqlError> {
/* You shouldn't have cum here.webm
* Basically sending messages with mysql is kinda painful so we
* do some special error checking by hand to see if
* a message was sent to an existing channel.
* The whole point of this is to avoid sending back a 500 to user clients
* which may cause confusing error handling in userland. This means we have
* confusing error handling on the server side but one of the parties has to
* do this stupid check so fuck it at least its mostly pointers anyway
*/
if let Err(e) = res {
return match e {
SqlError::Server(err) => {
if err.code == 1452 {
return Ok(Response::RestrictedInput("Channel not found".into()))
}
else {
Ok(Response::Other(sql_err!("db::messages::send")))
}
},
_ => Ok(Response::Other(sql_err!("db::messages::send")))
}
}
// all good response
else {
return Ok(Response::Row(passthrough));
}
}
pub async fn send(p: &Pool, content: &str, content_type: &str, cid: UBigInt, uid: UBigInt) -> Result<Response<Self>, SqlError> {
//! @returns on_sucess -> empty
//! @returns on_failure Err(SqlErr)
let conn = p.get_conn().await?;
let mut conn = p.get_conn().await?;
let q = "INSERT INTO messages
(id, time, content, content_type, author_id, channel_id)
VALUES (id, :time, :content, :ctype, :author, :channel)";
@ -84,7 +51,7 @@ impl Message {
if content.len() > 4_000 {
Ok(Response::RestrictedInput("Large text not allowed".into()))
} else {
let res = conn.prep_exec(q, params!{
let res = conn.exec_drop(q, params!{
"id" => id,
"time" => now,
"content" => content,
@ -92,8 +59,13 @@ impl Message {
"author" => uid,
"channel" => cid
}).await;
let msg = Message::new(id, now, content, content_type, uid, cid);
Self::message_passthrough_no_err(res, msg)
match Ok(res) {
Ok(_) => {
let msg = Message::new(id, now, content, content_type, uid, cid);
Ok(Response::Row(msg))
},
Err(e) => Err(e)
}
}
},
_ => {
@ -117,7 +89,7 @@ impl Message {
};
let content_ref = format!("{cid}-{time}.{ext}", cid=cid, time=now, ext=extension);
let res = conn.prep_exec(q, params!{
let res = conn.exec_drop(q, params!{
"id" => id,
"time" => now,
"content" => &content_ref, // store a ref to a file instead of the actual payload
@ -125,13 +97,13 @@ impl Message {
"author" => uid,
"channel" => cid
}).await;
let msg = Message::new(id, now, content, content_type, uid, cid);
if let Ok(ret) = Self::message_passthrough_no_err(res, msg) {
if let Ok(ret) = res {
// now save the data to disk
match fs::File::create(content_ref).await {
Ok(mut file) => {
file.write_all(content.as_bytes()).await.expect("Failed to write, but the ref is saved");
Ok(ret)
let msg = Message::new(id, now, content, content_type, uid, cid);
Ok(Response::Row(msg))
},
Err(_) => {
Ok(Response::Other("Saved ref but couldn't save file data".into()))
@ -156,7 +128,7 @@ impl Message {
Ok(Response::RestrictedInput("Invalid start/end parameters".into()))
}
else {
let conn = p.get_conn().await?;
let mut conn = p.get_conn().await?;
let limit = if let Some(limit) = limit {
match limit {
1 ..= MAX_MESSAGES => limit,
@ -172,17 +144,13 @@ impl Message {
WHERE channel_id = :channel AND time >= :start AND time < :end
LIMIT :limit";
let select_result = conn.prep_exec(
q, params!{
"start" => start,
"end" => end,
"channel" => channel_id,
"limit" => limit
}).await?;
let(_conn, messages) = select_result.map_and_drop(|row| {
type Tuple = (VarChar, UBigInt, BigInt, String, String, UBigInt);
let (name, id, time, content, content_type, author_id): Tuple = mysql_async::from_row(row);
let params = params!{
"start" => start,
"end" => end,
"channel" => channel_id,
"limit" => limit
};
let messages = conn.exec_map(q, params, |(name, id, time, content, content_type, author_id)| {
UserMessage {
id,
time,
@ -202,7 +170,7 @@ impl Message {
//! @returns on success : Set(Vec<Messages>)
//! @returns on user failure : RestrictedInput(String)
//! @returns on failure : Err(SqlError)
let conn = p.get_conn().await?;
let mut conn = p.get_conn().await?;
let limit = if let Some(limit) = limit{
match limit {
1 ..= MAX_MESSAGES => limit,
@ -221,11 +189,8 @@ impl Message {
"limit" => limit
};
let select_result = conn.prep_exec(q, params).await?;
let (_conn, messages) = select_result.map_and_drop(|row| {
type Tuple = (UBigInt, BigInt, VarChar, VarChar, UBigInt);
let (id, time, content, content_type, author_id): Tuple = mysql_async::from_row(row);
let messages = conn.exec_map(q, params,
|(id, time, content, content_type, author_id)| {
Self {
id,
time,