the compiler doesn't complain anymore but the server doesn't work aaa

This commit is contained in:
cqql 2024-09-01 13:48:41 +02:00
parent d1e73c5f44
commit 63e59f092e
5 changed files with 154 additions and 17 deletions

102
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,102 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'scct_migrations'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=scct-migrations"
],
"filter": {
"name": "scct_migrations",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'scct_server'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=scct-server"
],
"filter": {
"name": "scct_server",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'scct_model'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=scct-model"
],
"filter": {
"name": "scct_model",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'scct' server",
"cargo": {
"args": [
"build",
"--bin=scct",
"--package=scct-cli"
],
"filter": {
"name": "scct",
"kind": "bin"
}
},
"args": ["--debug", "serve"],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'scct'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=scct",
"--package=scct-cli"
],
"filter": {
"name": "scct",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

View file

@ -11,3 +11,20 @@ tldr:
* sea_orm and sqlx are huge but ehh db flexibility is nice feature * sea_orm and sqlx are huge but ehh db flexibility is nice feature
* i have no clue honestly * i have no clue honestly
* super cool chat thing yayyyyyyyy * super cool chat thing yayyyyyyyy
## Example serverbound messages
### Request chat history of chat room
The uuid is the chat room id
```json
{"RequestChatHistory":"00000000-0000-0000-0000-000000000000"}
```
### Send message to a chat room
```json
{"Message":{"id":"bef168ac-cee2-4319-9020-ef14a0778338","user_id":"67662e56-751a-4124-b611-0b54e53bd983","chat_id":"00000000-0000-0000-0000-000000000000","content":"hello world!","created":"2024-09-01T11:29:35.777275126Z","updated":null}}
```

View file

@ -22,15 +22,15 @@ pub mod c {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
#[test] #[test]
fn how_does_this_serialize_again() { fn example_message() {
panic!( panic!(
"{}", "{}",
serde_json::to_string( serde_json::to_string(
&super::c::Packet::Message( &super::s::Packet::Message(
crate::messages::Model { crate::messages::Model {
id: uuid::Uuid::new_v4(), id: uuid::Uuid::new_v4(),
user_id: uuid::Uuid::new_v4(), user_id: uuid::Uuid::new_v4(),
chat_id: uuid::Uuid::new_v4(), chat_id: uuid::Uuid::nil(),
content: Some("hello world!".to_string()), content: Some("hello world!".to_string()),
created: chrono::Utc::now(), created: chrono::Utc::now(),
updated: None, updated: None,
@ -39,4 +39,16 @@ mod test {
).expect("uhmmm???") ).expect("uhmmm???")
) )
} }
#[test]
fn example_request_chat_history() {
panic!(
"{}",
serde_json::to_string(
&super::s::Packet::RequestChatHistory(
uuid::Uuid::nil()
)
).expect("uhmmm???")
)
}
} }

View file

@ -4,7 +4,7 @@ use futures_util::FutureExt;
use scct_model::{chats, messages, proto::c2s, users}; use scct_model::{chats, messages, proto::c2s, users};
use sea_orm::{ActiveModelTrait, ConnectionTrait, DatabaseConnection, EntityTrait, IntoActiveModel, ColumnTrait, QueryFilter, QueryOrder}; use sea_orm::{ActiveModelTrait, ConnectionTrait, DatabaseConnection, EntityTrait, IntoActiveModel, ColumnTrait, QueryFilter, QueryOrder};
use tokio::sync::Mutex; use tokio::sync::Mutex;
use transport::{Transport, TransportSink, TransportStream, client_connection::ClientConnection}; use transport::{Transport, client_connection::ClientConnection};
use uuid; use uuid;
pub mod transport; pub mod transport;
@ -17,7 +17,7 @@ pub async fn serve(addr: &str, db_connection: DatabaseConnection) -> Result<(),
tracing::info!("preparing C2S transport"); tracing::info!("preparing C2S transport");
let mut listener = c2s.serve(addr.to_string()).await?; let mut listener = c2s.serve(addr.to_string()).await?;
// create the development chat if not exists // create the dev-test chat if it doesn't exist
if let Ok(None) = chats::Entity::find_by_id(uuid::Uuid::nil()).one(&db_connection).await { if let Ok(None) = chats::Entity::find_by_id(uuid::Uuid::nil()).one(&db_connection).await {
let chat = chats::Model { let chat = chats::Model {
id: uuid::Uuid::nil(), // temporarily we have only one chat id: uuid::Uuid::nil(), // temporarily we have only one chat
@ -31,9 +31,9 @@ pub async fn serve(addr: &str, db_connection: DatabaseConnection) -> Result<(),
tracing::info!("listening for connections"); tracing::info!("listening for connections");
while let Some((tx, rx)) = listener.recv().await { while let Some((tx, rx)) = listener.recv().await {
let client = ClientConnection::new((tx, rx)); let client = Arc::new(Mutex::new(ClientConnection::new((tx, rx))));
tracing::info!("new connection, starting handler"); tracing::info!("new connection, starting handler");
state.lock().await.push(&client); state.lock().await.push(client.clone());
let _state = state.clone(); let _state = state.clone();
let handler_db_conn = db_connection.clone(); let handler_db_conn = db_connection.clone();
@ -46,7 +46,7 @@ pub async fn serve(addr: &str, db_connection: DatabaseConnection) -> Result<(),
} }
/// Connection handler for handling a connecting client /// Connection handler for handling a connecting client
async fn handle_client_connection(active_client_peers: Arc<Mutex<Vec<&ClientConnection>>>, mut client: ClientConnection, db_connection: impl ConnectionTrait) { async fn handle_client_connection(active_client_peers: Arc<Mutex<Vec<Arc<Mutex<ClientConnection>>>>>, client: Arc<Mutex<ClientConnection>>, db_connection: impl ConnectionTrait) {
// for now we're creating a new user for each connection // for now we're creating a new user for each connection
let new_client_id = uuid::Uuid::new_v4(); let new_client_id = uuid::Uuid::new_v4();
let user = users::Model{ let user = users::Model{
@ -60,14 +60,16 @@ async fn handle_client_connection(active_client_peers: Arc<Mutex<Vec<&ClientConn
updated: None updated: None
}; };
let fn_span = tracing::span!(tracing::Level::TRACE, "handle_client_connection", client_uuid = client.uuid.to_string()); let fn_span = tracing::span!(tracing::Level::TRACE, "handle_client_connection", client_uuid = client.lock().await.uuid.to_string());
let _enter = fn_span.enter(); let _enter = fn_span.enter();
tracing::debug!("Inside handler for client connection: {}", client.lock().await.uuid);
user.clone().into_active_model().insert(&db_connection).await.expect("failed adding a new user for the connection"); user.clone().into_active_model().insert(&db_connection).await.expect("failed adding a new user for the connection");
// continuously waiting then receiving new messages // continuously waiting then receiving new messages
loop { loop {
match client.rx.pop().await { // match client.lock().await.rx.lock().await.pop().await {
Err(e) => { Err(e) => {
tracing::error!("error receiving from client: {e} -- stopping"); tracing::error!("error receiving from client: {e} -- stopping");
break; break;
@ -83,13 +85,14 @@ async fn handle_client_connection(active_client_peers: Arc<Mutex<Vec<&ClientConn
let mut disconnected_peers_to_remove = Vec::new(); let mut disconnected_peers_to_remove = Vec::new();
for (i, other_client) in active_client_peers.lock().await.iter_mut().enumerate() { for (i, other_client) in active_client_peers.lock().await.iter_mut().enumerate() {
if other_client.uuid == client.uuid { tracing::debug!("sending message from {} to {}", client.lock().await.uuid, other_client.lock().await.uuid);
if other_client.lock().await.uuid == client.lock().await.uuid {
// let's not transmit our message to ourselves // let's not transmit our message to ourselves
continue; continue;
} }
// try transmitting the message and if it fails, treat the client as disconnected // try transmitting the message and if it fails, treat the client as disconnected
if let Err(e) = other_client.tx.push(c2s::c::Packet::Message(msg.clone())).await { if let Err(e) = other_client.lock().await.tx.lock().await.push(c2s::c::Packet::Message(msg.clone())).await {
tracing::error!("failed broadcasting: {e}"); tracing::error!("failed broadcasting: {e}");
disconnected_peers_to_remove.push(i); disconnected_peers_to_remove.push(i);
} }
@ -110,7 +113,7 @@ async fn handle_client_connection(active_client_peers: Arc<Mutex<Vec<&ClientConn
Err(_) => { tracing::error!("failed to query all previously sent messages"); } Err(_) => { tracing::error!("failed to query all previously sent messages"); }
Ok(messages) => { Ok(messages) => {
tracing::info!("responding to RequestChatHistory: {}", serde_json::to_string(&messages).unwrap()); tracing::info!("responding to RequestChatHistory: {}", serde_json::to_string(&messages).unwrap());
match client.tx.push(c2s::c::Packet::MessagesHistory(messages)).await { match client.lock().await.tx.lock().await.push(c2s::c::Packet::MessagesHistory(messages)).await {
Ok(_) => {tracing::debug!("responding to RequestChatHistory was successful.")}, Ok(_) => {tracing::debug!("responding to RequestChatHistory was successful.")},
Err(e) => {tracing::error!("Failed to respond to RequestChatHistory: {}", e)}, Err(e) => {tracing::error!("Failed to respond to RequestChatHistory: {}", e)},
}; };

View file

@ -7,14 +7,17 @@
// when the user logs out. // when the user logs out.
// Basically lots of helper facilities. // Basically lots of helper facilities.
use std::sync::Arc;
use tokio::sync::Mutex;
use uuid::Uuid; use uuid::Uuid;
use super::{TransportSink, TransportStream}; use super::{TransportSink, TransportStream};
pub struct ClientConnection { pub struct ClientConnection {
pub uuid: Uuid, pub uuid: Uuid,
pub tx: Box<dyn TransportSink>, pub tx: Arc<Mutex<dyn TransportSink>>,
pub rx: Box<dyn TransportStream>, pub rx: Arc<Mutex<dyn TransportStream>>,
pub user_uuid: Option<Uuid> // gets set if and only if a user is logged in with this connection pub user_uuid: Option<Uuid> // gets set if and only if a user is logged in with this connection
} }
@ -22,8 +25,8 @@ impl ClientConnection {
pub fn new((tx, rx): (impl TransportSink + 'static, impl TransportStream + 'static)) -> ClientConnection { pub fn new((tx, rx): (impl TransportSink + 'static, impl TransportStream + 'static)) -> ClientConnection {
ClientConnection { ClientConnection {
uuid: Uuid::new_v4(), uuid: Uuid::new_v4(),
tx: Box::new(tx), tx: Arc::new(Mutex::new(tx)),
rx: Box::new(rx), rx: Arc::new(Mutex::new(rx)),
user_uuid: None, user_uuid: None,
} }
} }