➖ Removing more unused trait methods in db-lib's channel module
➕ /channels/list now takes a "type" parameter which defaults to TEXT_CHANNEL(1) ✨ Refactoring db::Channel::filter to use a more latency friendly approach ✨ db::Channel::Filter now returns Result<Response<Self>, SqlError>
This commit is contained in:
parent
fd1bf41fec
commit
fadc7d6dc1
@ -2,159 +2,44 @@ use mysql_async::{params, Pool, Conn};
|
||||
use mysql_async::prelude::Queryable;
|
||||
use mysql_async::error::Error as SqlError;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{VarChar, UBigInt, Integer};
|
||||
use crate::common::FromDB;
|
||||
use crate::{sql_err, no_conn, Response};
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Channel {
|
||||
pub id: UBigInt,
|
||||
pub name: VarChar,
|
||||
pub description: Option<VarChar>,
|
||||
pub kind: Integer
|
||||
}
|
||||
|
||||
pub const VOICE_CHANNEL: Integer = 1;
|
||||
pub const TEXT_CHANNEL: Integer = 2;
|
||||
|
||||
#[async_trait]
|
||||
impl FromDB<Channel, Integer> for Channel {
|
||||
// id name desc kind
|
||||
type Row = Option<(UBigInt, VarChar, Option<VarChar>, Integer)>;
|
||||
|
||||
async fn get(p: &Pool, id: UBigInt) -> Response<Channel> {
|
||||
//! Retrieves a Full single Channel row from the DB or fails in a
|
||||
//! fashion described by crate::Response<Channel>
|
||||
//! @param p -> SqlPool
|
||||
//! @param id -> UBigInt
|
||||
//! @return on_success -> Response::Row(Channel)
|
||||
//! @return on_fail -> Response::{Empty, Other<String>}
|
||||
if let Ok(conn) = p.get_conn().await {
|
||||
let q = "SELECT id, name, description, kind FROM channels WHERE id = :id";
|
||||
let result: Result<(Conn, Self::Row), SqlError> =
|
||||
conn.first_exec(q, params!{"id" => id}).await;
|
||||
if let Ok((_, row)) = result {
|
||||
return match row {
|
||||
Some(row) => Response::Row(Channel {
|
||||
id,
|
||||
name: row.1,
|
||||
description: row.2,
|
||||
kind: row.3
|
||||
impl crate::Channel {
|
||||
pub async fn filter(p: &Pool, kind: Integer) -> Result<Response<Self>, SqlError> {
|
||||
//! @returns -> on success : Ok(Response::Set(Vec<Channel>))
|
||||
//! @throw -> on sql fail : Err(SqlError)
|
||||
|
||||
}),
|
||||
None => Response::Empty
|
||||
if kind != VOICE_CHANNEL || kind !=TEXT_CHANNEL {
|
||||
let conn = p.get_conn().await?;
|
||||
let q = "SELECT id, name, description FROM channels WHERE kind = :kind";
|
||||
|
||||
let result = conn.prep_exec(q, params!{"kind" => kind}).await?;
|
||||
let (_conn, channels) = result.map_and_drop(|row| {
|
||||
let (id, name, description): (UBigInt, VarChar, Option<VarChar>) =
|
||||
mysql_async::from_row(row);
|
||||
Self {
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
kind
|
||||
}
|
||||
}
|
||||
return Response::Other(no_conn!("Invite::FromDB::get fetch failed"));
|
||||
}
|
||||
return Response::Other(no_conn!("Invite::FromDB::get"));
|
||||
}
|
||||
}).await?;
|
||||
|
||||
async fn update(p: &Pool, row: Self) -> Response<Channel> {
|
||||
//! Updates a whole single based on a given Row Of Channel Type
|
||||
//! @param p -> SqlPool
|
||||
//! @param row -> Channel
|
||||
//! @return on_success -> Response::Success
|
||||
//! @return on_failure -> Response::Other
|
||||
if let Ok(conn) = p.get_conn().await {
|
||||
let q = "UPDATE channels
|
||||
SET name = :name, description = :desc, kind = :kind
|
||||
WHERE id = :id";
|
||||
let result: Result<Conn, SqlError> =
|
||||
conn.drop_exec(q, params!{
|
||||
"id" => row.id,
|
||||
"name" => row.name,
|
||||
"desc" => row.description,
|
||||
"kind" => row.kind
|
||||
}).await;
|
||||
return match result {
|
||||
Ok(_) => Response::Success,
|
||||
Err(_) => Response::Other(sql_err!("Invite::FromDB::update Update failed"))
|
||||
}
|
||||
}
|
||||
return Response::Other(no_conn!("Invite::FromDB::get connection failed"));
|
||||
}
|
||||
|
||||
async fn delete(p: &Pool, id: UBigInt) -> Response<Channel> {
|
||||
//! Deletes channel given UBigInt as the row key
|
||||
//! @param p -> SqlPool
|
||||
//! @param id -> UBigInt
|
||||
//! @return on success -> Response::Success
|
||||
//! @return on server failure -> Response::Other
|
||||
if let Ok(conn) = p.get_conn().await {
|
||||
let q = "DELETE FROM channels WHERE id = :id";
|
||||
let result: Result<Conn, SqlError> =
|
||||
conn.drop_exec(q, params!{"id" => id}).await;
|
||||
return match result {
|
||||
Ok(_) => Response::Success,
|
||||
Err(sql) => Response::Other(sql_err!(sql))
|
||||
}
|
||||
Ok(Response::Set(channels))
|
||||
}
|
||||
else {
|
||||
return Response::Other(no_conn!("Member::FromDB::delete"))
|
||||
return Ok(Response::RestrictedInput("Channel kind is invalid".into()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async fn filter(p: &Pool, kind: Integer) -> Response<Channel> {
|
||||
//! @returns -> on success : Response::Set(Vec<Channel>)
|
||||
//! @returns -> on empty set : Response::Set(EmptyVector)
|
||||
//! @params -> on fail : Response::Other
|
||||
|
||||
// NOTE: used for mapping datasets to vectors
|
||||
let map_rows = |row| {
|
||||
let (id, name, desc, k): (UBigInt, VarChar, Option<VarChar>, Integer) =
|
||||
mysql_async::from_row(row);
|
||||
Channel {
|
||||
id,
|
||||
name,
|
||||
description: desc,
|
||||
kind: k
|
||||
}
|
||||
};
|
||||
return match (p.get_conn().await, kind) {
|
||||
// Filter for text/voice channels specifically
|
||||
(Ok(conn), VOICE_CHANNEL..=TEXT_CHANNEL) => { // @NOTE: voice channel and text_channel are literally 1 & 2 respectively
|
||||
let q = "SELECT id, name, description, kind FROM channels WHERE kind = :kind";
|
||||
let q_result = conn.prep_exec(q, params!{"kind" => kind}).await;
|
||||
if let Ok(res) = q_result {
|
||||
let mapping_result = res.map_and_drop(map_rows).await;
|
||||
return match mapping_result {
|
||||
Ok((_, channels)) => Response::Set(channels),
|
||||
Err(_) => Response::Other(sql_err!("db::Channels::filter @with params"))
|
||||
};
|
||||
}
|
||||
else {
|
||||
Response::Other(sql_err!(""))
|
||||
}
|
||||
},
|
||||
/*
|
||||
* Here we are attempting to get all the channels with no filters applied
|
||||
* This should fetch everything basically in our channels registry
|
||||
*/
|
||||
(Ok(conn), _) => {
|
||||
let q = "SELECT id, name, description, kind FROM channels";
|
||||
if let Ok(query) = conn.prep_exec(q, ()).await {
|
||||
let mapping_r = query.map_and_drop(map_rows).await;
|
||||
|
||||
return match mapping_r {
|
||||
Ok((_, channels)) => Response::Set(channels),
|
||||
Err(_) => Response::Other(sql_err!("db::Channels::filter @no params"))
|
||||
};
|
||||
}
|
||||
else {
|
||||
Response::Other(sql_err!("db::Channels::filter @no params @no initial query"))
|
||||
}
|
||||
},
|
||||
(Err(_), _) => {Response::Other(no_conn!("Channel::FromDB::filter"))}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Channel {
|
||||
pub async fn new(p: &Pool, name: &str, desc: &str, kind: Integer) -> Response<Self> {
|
||||
//! @returns on success -> Response::Row<Channel>
|
||||
//! @returns on partial success -> Response::Empty
|
||||
@ -176,7 +61,7 @@ impl Channel {
|
||||
return match fetch_result {
|
||||
Ok((_, id_opt)) => {
|
||||
if let Some(id) = id_opt {
|
||||
Response::Row(Channel {
|
||||
Response::Row(Self {
|
||||
id,
|
||||
name: name.into(),
|
||||
description: Some(desc.into()),
|
||||
@ -194,6 +79,28 @@ impl Channel {
|
||||
}
|
||||
}
|
||||
return Response::Other(no_conn!("db::channels::add"))
|
||||
}
|
||||
|
||||
pub async fn delete(p: &Pool, id: UBigInt) -> Response<Self> {
|
||||
//! Deletes channel given UBigInt as the row key
|
||||
//! @param p -> SqlPool
|
||||
//! @param id -> UBigInt
|
||||
//! @return on success -> Response::Success
|
||||
//! @return on server failure -> Response::Other
|
||||
if let Ok(conn) = p.get_conn().await {
|
||||
let q = "DELETE FROM channels WHERE id = :id";
|
||||
let result: Result<Conn, SqlError> =
|
||||
conn.drop_exec(q, params!{"id" => id}).await;
|
||||
return match result {
|
||||
Ok(_) => Response::Success,
|
||||
Err(sql) => Response::Other(sql_err!(sql))
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Response::Other(no_conn!("Member::FromDB::delete"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,14 @@ pub struct UserMessage {
|
||||
pub name: VarChar
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Channel {
|
||||
pub id: UBigInt,
|
||||
pub name: VarChar,
|
||||
pub description: Option<VarChar>,
|
||||
pub kind: Integer
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fetch_row {
|
||||
($table:literal, $col:literal, $key:expr, $rtype:ty,$conn:expr) => {
|
||||
|
@ -6,28 +6,33 @@ use serde_json::json;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use db::{
|
||||
self,
|
||||
common::FromDB,
|
||||
channels::Channel
|
||||
};
|
||||
use db::{ self, common::FromDB, Channel };
|
||||
|
||||
use crate::http::set_json_body;
|
||||
use crate::qs_param;
|
||||
|
||||
|
||||
pub async fn list_channels(pool: &Pool, response: &mut Response<Body>) {
|
||||
pub async fn list_channels(pool: &Pool, response: &mut Response<Body>, params: HashMap<String, String>) {
|
||||
/*
|
||||
* @user-params -> for now none as i don't feel like dealing with it
|
||||
* @TODO: add in a let var that actually
|
||||
*/
|
||||
return match db::channels::Channel::filter(pool, 0).await {
|
||||
db::Response::Set(channels) => {
|
||||
set_json_body(response, json!({"channels": channels}));
|
||||
},
|
||||
db::Response::Other(_msg) => *response.status_mut() = hyper::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
_ => *response.status_mut() = hyper::StatusCode::INTERNAL_SERVER_ERROR,
|
||||
|
||||
// Default to filtering for text channels only
|
||||
let chan_type = match qs_param!(params, "type", i32) {
|
||||
Some(ctype) => ctype,
|
||||
None => db::channels::TEXT_CHANNEL
|
||||
};
|
||||
|
||||
match db::Channel::filter(pool, chan_type).await {
|
||||
Ok(resp) => match resp {
|
||||
db::Response::Set(channels) => set_json_body(response, json!(channels)),
|
||||
_ => *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR
|
||||
},
|
||||
Err(e) => {
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn create_channel(pool: &Pool, response: &mut Response<Body>, params: HashMap<String, String>) {
|
||||
|
@ -61,7 +61,7 @@ async fn route_dispatcher(
|
||||
(POST, routes::INVITE_CREATE) => invites::create(pool, resp, params).await,
|
||||
(GET, routes::INVITE_JOIN) => invites::join(pool, resp, params).await,
|
||||
/* CHANNELS */
|
||||
(GET, routes::CHANNELS_LIST) => channels::list_channels(pool, resp).await,
|
||||
(GET, routes::CHANNELS_LIST) => channels::list_channels(pool, resp, params).await,
|
||||
(POST, routes::CHANNELS_CREATE) => channels::create_channel(pool, resp, params).await,
|
||||
(DELETE, routes::CHANNELS_DELETE) => channels::delete_channel(pool, resp, params).await,
|
||||
/* MESSAGING */
|
||||
|
Loading…
Reference in New Issue
Block a user