From 422109b4b01121c7e185b3c20df6945da748a6d9 Mon Sep 17 00:00:00 2001 From: Joshua Higgins Date: Fri, 28 Jun 2024 23:22:57 -0400 Subject: [PATCH] Change to sqlx, started send_message --- server/.env | 1 + server/Cargo.toml | 4 ++- server/src/main.rs | 55 ++++++++++++++++++++++------- server/src/server.rs | 83 ++++++++++++++++++++++++-------------------- server/src/types.rs | 23 +++++------- 5 files changed, 100 insertions(+), 66 deletions(-) create mode 100644 server/.env diff --git a/server/.env b/server/.env new file mode 100644 index 0000000..9fa7b5a --- /dev/null +++ b/server/.env @@ -0,0 +1 @@ +DATABASE_URL=mysql://root:strong_password@localhost:3307/ \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index 410f329..6314084 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -12,4 +12,6 @@ tracing = "0.1.40" clap = { version = "4.5.7", features = ["derive"] } serde = { version = "1.0.203", features = ["derive"] } emojis = "0.6.2" -surrealdb = "1.5.3" +chrono = { version = "0.4.24", features = ["serde"] } +sqlx = { version = "0.7", features = [ "runtime-tokio", "tls-rustls", "mysql" ] } +dotenvy = "0.15" \ No newline at end of file diff --git a/server/src/main.rs b/server/src/main.rs index f81a1f9..13f7c47 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,11 +1,10 @@ +use std::env; use std::future::Future; use std::net::{IpAddr, Ipv6Addr}; -use std::sync::Arc; +use dotenvy::dotenv; use futures::future::{self}; use futures::StreamExt; -use surrealdb::engine::remote::ws::Ws; -use surrealdb::opt::auth::Root; -use surrealdb::Surreal; +use sqlx::mysql::MySqlPoolOptions; use tarpc::{ server::{Channel}, tokio_serde::formats::Json, @@ -21,17 +20,47 @@ async fn spawn(fut: impl Future + Send + 'static) { #[tokio::main] async fn main() -> anyhow::Result<()> { - // Connect to the server - let db = Arc::new(Surreal::new::("127.0.0.1:8000").await?); + dotenv().ok(); + + let db_pool = MySqlPoolOptions::new() + .max_connections(64) + .connect(env::var("DATABASE_URL").expect("DATABASE_URL must be set").as_str()).await?; + + sqlx::query( + "CREATE DATABASE IF NOT EXISTS realmchat; USE realmchat;" + ).fetch_one(&db_pool).await?; - // Signin as a namespace, database, or root user - db.signin(Root { - username: "root", - password: "root", - }).await?; + sqlx::query( + "CREATE TABLE IF NOT EXISTS room ( + id SERIAL, + room_id VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL + );" + ).execute(&db_pool).await?; - // Select a specific namespace / database - db.use_ns("realmchat").use_db("test").await?; + sqlx::query( + "CREATE TABLE IF NOT EXISTS user ( + id SERIAL, + user_id VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + online BOOL NOT NULL + );" + ).execute(&db_pool).await?; + + sqlx::query( + "CREATE TABLE IF NOT EXISTS message ( + id SERIAL, + timestamp DATETIME NOT NULL, + user INT NOT NULL, + room INT NOT NULL, + type ENUM('text', 'attachment', 'reply', 'edit', 'reaction', 'redaction') NOT NULL, + + msgText TEXT, + referencingID INT, + emoji TEXT, + redaction BOOL + );" + ).execute(&db_pool).await?; let server_addr = (IpAddr::V6(Ipv6Addr::LOCALHOST), 5051); diff --git a/server/src/server.rs b/server/src/server.rs index 6714f3b..8f3a3f0 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -1,23 +1,23 @@ use std::net::SocketAddr; -use std::sync::Arc; + use futures::future; use futures::future::Ready; -use surrealdb::engine::remote::ws::Client; -use surrealdb::{Error, Response, Surreal}; +use sqlx::{MySql, Pool}; use tarpc::context::Context; -use crate::types::{Message, RealmChat, Room, ErrorCode, User, Record}; +use tarpc::server::incoming::Incoming; +use crate::types::{ErrorCode, Message, MessageData, RealmChat, Room, User}; #[derive(Clone)] pub struct RealmChatServer { pub socket: SocketAddr, - pub db: Arc>, + pub db_pool: Pool, } impl RealmChatServer { - pub fn new(socket: SocketAddr, db: Arc>) -> RealmChatServer { + pub fn new(socket: SocketAddr, db_pool: Pool) -> RealmChatServer { RealmChatServer { socket, - db, + db_pool, } } } @@ -28,15 +28,43 @@ impl RealmChat for RealmChatServer { } async fn send_message(self, context: Context, message: Message) -> Result { - let created: surrealdb::Result> = self.db - .create(message.room.roomid.clone()) - .content(message.clone()) - .await; + //TODO: verify authentication somehow - //TODO: Tell everyone + let result = match &message.data { + MessageData::Text(text) => { + sqlx::query("INSERT INTO message (timestamp, user, room, type, msgText) VALUES (?, ?, ?, 'text', ?)") + .bind(message.timestamp).bind(message.user.id).bind(message.room.id).bind(text) + .execute(&self.db_pool).await + } + MessageData::Attachment(attachment) => { todo!() } + MessageData::Reply(reply) => { + sqlx::query("INSERT INTO message (timestamp, user, room, type, msgText, referencingID) VALUES (?, ?, ?, 'reply', ?, ?)") + .bind(message.timestamp).bind(message.user.id).bind(message.room.id).bind(reply.text.clone()).bind(reply.referencing_id) + .execute(&self.db_pool).await + } + MessageData::Edit(edit) => { + sqlx::query("INSERT INTO message (timestamp, user, room, type, msgText, referencingID) VALUES (?, ?, ?, 'edit', ?, ?)") + .bind(message.timestamp).bind(message.user.id).bind(message.room.id).bind(edit.text.clone()).bind(edit.referencing_id) + .execute(&self.db_pool).await + } + MessageData::Reaction(reaction) => { + sqlx::query("INSERT INTO message (timestamp, user, room, type, emoji, referencingID) VALUES (?, ?, ?, 'reaction', ?, ?)") + .bind(message.timestamp).bind(message.user.id).bind(message.room.id).bind(reaction.emoji.clone()).bind(reaction.referencing_id) + .execute(&self.db_pool).await + } + MessageData::Redaction(redaction) => { + sqlx::query("INSERT INTO message (timestamp, user, room, type, redaction, referencingID) VALUES (?, ?, ?, 'redaction', ?, ?)") + .bind(message.timestamp).bind(message.user.id).bind(message.room.id).bind(true).bind(redaction.referencing_id) + .execute(&self.db_pool).await + } + }; - match created { - Ok(ids) => Ok(message), + match result { + Ok(ids) => { + //TODO: Tell everyone + + Ok(message) + }, Err(_) => Err(ErrorCode::Error), } } @@ -62,12 +90,7 @@ impl RealmChat for RealmChatServer { } async fn get_rooms(self, context: Context) -> Result, ErrorCode> { - let result: surrealdb::Result> = self.db.select("room").await; - - match result { - Ok(rooms) => Ok(rooms), - Err(_) => Err(ErrorCode::Error), - } + todo!() } async fn get_room(self, context: Context, roomid: String) -> Result { @@ -79,26 +102,10 @@ impl RealmChat for RealmChatServer { } async fn get_joined_users(self, context: Context) -> Result, ErrorCode> { - let result: surrealdb::Result> = self.db.select("user").await; - - match result { - Ok(users) => Ok(users), - Err(_) => Err(ErrorCode::Error), - } + todo!() } async fn get_online_users(self, context: Context) -> Result, ErrorCode> { - let result: surrealdb::Result = self.db.query("SELECT * FROM user WHERE online = true").await; //TODO: We're switching to MySQL - - match result { - Ok(mut response) => { - let users: Result, Error> = response.take(0); - match users { - Ok(vec) => Ok(vec), - Err(_) => Err(ErrorCode::Error), - } - }, - Err(_) => Err(ErrorCode::Error), - } + todo!() } } \ No newline at end of file diff --git a/server/src/types.rs b/server/src/types.rs index a197024..0b15099 100644 --- a/server/src/types.rs +++ b/server/src/types.rs @@ -1,11 +1,5 @@ -use surrealdb::sql::Thing; use tarpc::serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize)] -pub struct Record { - id: Thing, -} - #[tarpc::service] pub trait RealmChat { async fn test(name: String) -> String; @@ -31,7 +25,7 @@ pub trait RealmChat { #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ErrorCode { - None = 0, + None, Error, Unauthorized, NotFound, @@ -39,8 +33,8 @@ pub enum ErrorCode { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { - pub guid: String, - pub timestamp: u64, + pub id: u32, + pub timestamp: u64, //TODO: Change to a real time for SQL pub user: User, pub room: Room, pub data: MessageData, @@ -55,7 +49,6 @@ pub enum MessageData { Edit(Edit), //NOTE: Have to be the owner of the referencing_guid Reaction(Reaction), Redaction(Redaction), - TypingIndicator(bool), //isTyping } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -65,29 +58,30 @@ pub struct Attachment { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Reply { - pub referencing_guid: String, + pub referencing_id: u32, pub text: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Edit { - pub referencing_guid: String, + pub referencing_id: u32, pub text: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Reaction { - pub referencing_guid: String, + pub referencing_id: u32, pub emoji: String } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Redaction { - pub referencing_guid: String, + pub referencing_id: u32, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct User { + pub id: u32, pub userid: String, pub name: String, pub online: bool, @@ -96,6 +90,7 @@ pub struct User { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Room { + pub id: u32, pub roomid: String, pub name: String, //TODO