Removal of chrono and async_trait as dependancy in db-lib

Removig chrono from api code as well
This commit is contained in:
shockrah 2021-03-20 13:56:02 -07:00
parent cb5975f235
commit ba14600b34
7 changed files with 61 additions and 1808 deletions

1576
json-api/db/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,5 @@ edition = "2018"
mysql_async = "0.23.1"
async-trait = "0.1.40"
serde_json = "1.0"
serde = { version = "1.0.117", features = [ "derive" ] }
chrono = "0.4.0"

View File

@ -1,9 +1,3 @@
use mysql_async::Pool;
use async_trait::async_trait;
use crate::Response;
use crate::UBigInt;
#[macro_export]
macro_rules! no_conn {
($spec:literal) => {
@ -30,24 +24,3 @@ macro_rules! sql_err_log {
}
}
/*
* NOTE: pay attention to work on async in traits for rust
* Each of one these funcs will implicitly do a single heap allocation which
* for our case is fine though ideally we don't
*
* As soon as we finda way around that we should depecrate `#[async_trait`
* for the performance
* */
#[async_trait]
pub trait FromDB<T, FilterType> {
type Row;
async fn get(p: &Pool, id: UBigInt) -> Response<T>;
async fn update(p: &Pool, row: T) -> Response<T>;
async fn delete(p: &Pool, id: UBigInt) -> Response<T>;
async fn filter(p: &Pool, filter_val: FilterType) -> Response<T>;
}

View File

@ -1,132 +1,50 @@
use mysql_async::{params, Pool, Conn};
use std::time::{SystemTime, Duration, UNIX_EPOCH};
use mysql_async::{params, Pool};
use mysql_async::prelude::Queryable;
use mysql_async::error::Error as SqlError;
use serde::Serialize;
use async_trait::async_trait;
use crate::{BigInt, Invite, Response};
use crate::{UBigInt, BigInt};
use crate::common::FromDB;
use crate::{Response, no_conn};
#[allow(dead_code)]
#[derive(Serialize, Debug)]
pub struct Invite {
pub id: BigInt,
pub uses: Option<BigInt>,
pub expires: bool
}
#[async_trait]
impl FromDB<Invite, bool> for Invite {
type Row = Option<(BigInt, Option<BigInt>, bool)>;
async fn get(p: &Pool, id: UBigInt) -> Response<Self> {
impl Invite {
pub async fn get(p: &Pool, id: BigInt) -> Result<Response<Self>, SqlError> {
// NOTE: cast is required for this as `id` is used as unix timestamp
let id: BigInt = id as BigInt;
if id <= 0 {
return Response::Empty;
return Ok(Response::RestrictedInput(format!("<{}> not found", id)))
}
if let Ok(conn) = p.get_conn().await {
let q = "SELECT id, uses, expires FROM invites WHERE id = :id ";
let result: Result<(Conn, Self::Row), SqlError> =
conn.first_exec(q, params!{"id" => id}).await;
let conn = p.get_conn().await?;
let q = "SELECT uses, expires FROM invites WHERE id = :id ";
let (_, data_row): (_, Option<(Option<BigInt>, bool)>) =
conn.first_exec(q, params!{"id" => id}).await?;
if let Ok((_, row)) = result {
return match row {
Some(row) => Response::Row(Self {
id: id as BigInt,
uses: row.1,
expires: row.2
}),
None => Response::Empty
}
}
return if let Some(row) = data_row {
Ok(Response::Row(Invite{
id,
uses: row.0,
expires: row.1,
}))
} else {
Ok(Response::Empty)
}
return Response::Empty;
}
async fn update(p: &Pool, row: Self) -> Response<Self> {
let q = r#"UPDATE invites
SET uses = :uses, expires: :exp
WHERE id = :id
"#;
// forcibly udpate even if theres nothing there
// this way we avoid doing an extra network hit
if row.id <= 0 {
return Response::Empty;
}
if let Ok(conn) = p.get_conn().await {
let result: Result<Conn, SqlError> =
conn.drop_exec(q, params!{
"id" => row.id,
"uses" => row.uses,
"exp" => row.expires
}).await;
return match result {
Ok(_) => Response::Success,
Err(_) => Response::Other(format!("Could not update entry {}", row.id))
}
}
return Response::Empty;
}
async fn delete(p: &Pool, id: UBigInt) -> Response<Self> {
if id <= 0 { // really lame "assertion" that each method has to use for invites since they all internally use
return Response::Empty;
}
if let Ok(conn) = p.get_conn().await {
let q = "DELETE FROM invites WHERE id = :id";
let result: Result<Conn, SqlError> =
conn.drop_exec(q, params!{"id" => id as BigInt}).await;
return match result {
Ok(_) => Response::Success,
Err(_) => Response::Other(format!("Could not delete {}", id))
}
}
return Response::Success;
}
async fn filter(p: &Pool, expirey_flag: bool) -> Response<Self> {
if let Ok(conn) = p.get_conn().await {
let q = "SELECT id, uses, expires FROM invites WHERE expires = :exp";
if let Ok(query) = conn.prep_exec(q, params!{"exp" => expirey_flag}).await {
let mapping_r = query.map_and_drop(|row| {
let (id, uses): (BigInt, Option<BigInt>) = mysql_async::from_row(row);
Invite {
id,
uses,
expires: expirey_flag
}
}).await;
return match mapping_r {
Ok((_, invites)) => Response::Set(invites),
Err(_) => Response::Empty
}
}
else {
return Response::Other(no_conn!("db::Invite::filter"));
}
}
else {
return Response::Other(no_conn!("db::Invites::filter"));
}
}
}
impl Invite {
pub fn new(uses: Option<i64>, expires: bool) -> Invite {
use chrono::Utc;
// now + 30 minutes
let later = SystemTime::now() + Duration::from_secs(60 * 30);
let id: i64 = later.duration_since(UNIX_EPOCH).expect("honestly idk").as_millis() as i64;
Invite {
id: (Utc::now() + chrono::Duration::minutes(30)).timestamp_millis(),
id,
uses,
expires
}
}
pub async fn add(&self, p: &Pool) -> Result<(), SqlError> {
let conn = p.get_conn().await?;
@ -140,4 +58,5 @@ impl Invite {
Ok(())
}
}

View File

@ -66,13 +66,19 @@ pub struct Channel {
pub kind: Integer
}
#[macro_export]
macro_rules! fetch_row {
($table:literal, $col:literal, $key:expr, $rtype:ty,$conn:expr) => {
let lib_str = format!("SELECT * FROM {} WHERE {} = :{}", $table, $col, $col);
let (_, $rtype) = $conn.first_exec!(lib_str, sql_params{
$col => $key,
});
}
#[derive(Serialize, Debug)]
pub struct Invite {
pub id: BigInt,
pub uses: Option<BigInt>,
pub expires: bool
}
#[derive(Debug, Serialize)]
pub struct Member {
pub id: UBigInt,
pub secret: VarChar,
pub name: VarChar,
pub status: Integer,
pub permissions: UBigInt,
}

View File

@ -2,24 +2,12 @@ use mysql_async::{params, Pool, Conn};
use mysql_async::prelude::Queryable;
use mysql_async::error::Error as SqlError;
use async_trait::async_trait;
use serde::Serialize;
use crate::{Response, no_conn, sql_err};
use crate::{UBigInt, BigInt, Integer, VarChar};
use crate::{UBigInt, Integer, VarChar};
use crate::Member;
use crate::common::FromDB;
#[derive(Debug, Serialize)]
pub struct Member {
pub id: UBigInt,
pub secret: VarChar,
pub name: VarChar,
pub joindate: BigInt,
pub status: Integer,
pub permissions: UBigInt,
}
pub const STATUS_ONLINE: Integer = 0;
@ -33,16 +21,14 @@ pub const STATUS_DO_NOT_DISTURB: Integer = 3;
* return response based on result
*
*/
#[async_trait]
impl FromDB<Member, Integer> for Member {
type Row = Option<(VarChar, VarChar, BigInt, Integer, UBigInt)>;
async fn get(p: &Pool, id: UBigInt) -> Response<Self> {
impl Member {
pub async fn get(p: &Pool, id: UBigInt) -> Response<Self> {
//! @returns Row on success
//! @returns Other on failure
if let Ok(conn) = p.get_conn().await {
let q = "SELECT secret, name, joindate, status, permissions FROM members WHERE id = :id";
let db_res : Result<(Conn, Self::Row), SqlError>
let q = "SELECT secret, name, status, permissions FROM members WHERE id = :id";
type Row = Option<(VarChar, VarChar, Integer, UBigInt)>;
let db_res : Result<(Conn, Row), SqlError>
= conn.first_exec(q, params!{"id" => id}).await;
if let Ok((_, row)) = db_res {
return match row {
@ -50,9 +36,8 @@ impl FromDB<Member, Integer> for Member {
id,
secret: row.0,
name: row.1,
joindate: row.2,
status: row.3,
permissions: row.4
status: row.2,
permissions: row.3
}),
None => Response::Empty
}
@ -62,52 +47,8 @@ impl FromDB<Member, Integer> for Member {
return Response::Other(no_conn!("Member::FromDB::get"));
}
async fn update(p: &Pool, row: Member) -> Response<Self> {
let q = r#"UPDATE members
SET status = :status, permissions = :perms, name = :name
WHERE id = :id"#;
if let Ok(conn) = p.get_conn().await {
let query = conn.drop_exec(q, params!{
"id" => row.id,
"status" => row.status,
"name" => row.name,
"perms" => row.permissions
}).await;
return match query {
Ok(_) => Response::Success,
Err(err) => Response::Other(sql_err!(err))
}
}
return Response::Other(no_conn!("db::Member::update"));
}
async fn delete(p: &Pool, id: UBigInt) -> Response<Self> {
if let Ok(conn) = p.get_conn().await {
let q = "DELETE from members WHERE id = :id";
let db_result: Result<Conn, SqlError>
= conn.drop_exec(q, params!{"id" => id}).await;
match Member::get(p, id).await {
Response::Row(_) => {
if let Ok(conn) = db_result {
return match conn.prep_exec("", params!{"id" => id}).await {
Ok(_) => Response::Success,
Err(_) => Response::Other(sql_err!("Member::FromDB::delete"))
}
}
return Response::Success
},
Response::Empty => return Response::Empty,
_ => return Response::Other(sql_err!("Member::FromDB::delete | another stupid get happened delid this"))
}
}
return Response::Empty;
}
async fn filter(p: &Pool, status: Integer) -> Response<Self> {
pub async fn filter(p: &Pool, status: Integer) -> Response<Self> {
//! @params status
return match (p.get_conn().await, status) {
(Ok(conn), STATUS_ONLINE) | (Ok(conn), STATUS_OFFLINE) |
@ -127,7 +68,6 @@ impl FromDB<Member, Integer> for Member {
id,
secret: "".into(), // no show for obv reasons
name,
joindate: 0, // doesn't matter
status,
permissions
}
@ -144,9 +84,6 @@ impl FromDB<Member, Integer> for Member {
_ => Response::Other(sql_err!("err"))
}
}
}
impl Member {
pub async fn add(p: &Pool, name: &str, secret: &str, perms: u64) -> Result<Response<Self>, SqlError> {
//! @param {pool} p
//! @param {&str} name of new user
@ -156,23 +93,15 @@ impl Member {
//! @returns : on_succes => Ok(Response<Member>)
//! @returns : on_partial_succes => Ok(Response<Member>)
//! @returns : on_failure => Err(SomeBS)
use chrono::Utc;
let conn = p.get_conn().await?;
//name
//perms
//secret
let now: BigInt = Utc::now().timestamp();
let conn = conn.drop_exec(
"INSERT INTO members(secret, name, joindate, status, permissions)
VALUES(:secret, :name, :joindate, :status, :permissions)",
"INSERT INTO members(secret, name, status, permissions)
VALUES(:secret, :name, :status, :permissions)",
mysql_async::params!{
"secret" => secret.clone(),
"name" => name.clone(),
"joindate" => now,
"status" => STATUS_ONLINE,
"permissions" => perms
}).await?;
@ -188,7 +117,6 @@ impl Member {
id,
secret: secret.into(),
name: name.into(),
joindate: now,
status: STATUS_ONLINE,
permissions: perms
}))

View File

@ -1,3 +1,5 @@
use std::time::{SystemTime, UNIX_EPOCH};
use mysql_async::{params, Pool};
use mysql_async::prelude::Queryable;
use mysql_async::error::Error as SqlError;
@ -5,22 +7,25 @@ use mysql_async::error::Error as SqlError;
use crate::{Response, sql_err};
use crate::{UBigInt, BigInt, VarChar};
use crate::UserMessage;
use crate::{Message, UserMessage};
const MAX_MESSAGES: u64 = 1000;
impl crate::Message {
impl Message {
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)
use chrono::Utc;
let conn = p.get_conn().await?;
let q = "INSERT INTO messages
(time, content, content_type, author_id, channel_id)
VALUES (:time, :content, :ctype, :author, :channel)";
let now = Utc::now().timestamp();
let now: i64 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("System time `NOW` failed")
.as_millis() as i64;
let res = conn.prep_exec(q, params!{
"time" => now,