Switch to object oriented message format

This commit is contained in:
Lucas Schumacher 2023-11-05 17:00:17 -05:00
parent cd57573288
commit 6d24f03648
4 changed files with 33 additions and 13 deletions

5
Cargo.lock generated
View File

@ -508,6 +508,7 @@ dependencies = [
"poem", "poem",
"poem-openapi", "poem-openapi",
"serde", "serde",
"serde_json",
"sqlx", "sqlx",
"thiserror", "thiserror",
"tokio", "tokio",
@ -1620,9 +1621,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.107" version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",

View File

@ -14,4 +14,5 @@ poem-openapi = { version = "3.0.5", features = ["websocket"] }
serde = "1.0.190" serde = "1.0.190"
thiserror = "1.0.50" thiserror = "1.0.50"
anyhow = "1.0.75" anyhow = "1.0.75"
serde_json = "1.0.108"

View File

@ -5,7 +5,7 @@ const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const input = ref('') const input = ref('')
const msgs = ref(['Server: Welcome to chat app', 'Server: This is an example message']) const msgs = ref([{ username: 'Server', message: 'Welcome to Chat App' }, { username: 'Server', message: 'This is an example message' }])
let ws; let ws;
async function sendMsg(ev) { async function sendMsg(ev) {
@ -29,9 +29,10 @@ onMounted(async () => {
window.location.hash = "/login" window.location.hash = "/login"
}; };
ws.onmessage = function (event) { ws.onmessage = async function (event) {
console.log(event) console.log("event data: " + event.data)
msgs.value.push(event.data) msgs.value.push(JSON.parse(event.data))
console.log("msgs:" + msgs.value)
}; };
console.log(ws) console.log(ws)
@ -42,12 +43,12 @@ onMounted(async () => {
<main> <main>
<div class="overflow-auto position-relative pb-5"> <div class="overflow-auto position-relative pb-5">
<div v-for="msg in msgs" class="card m-3 text-bg-secondary"> <div v-for="msg in msgs" class="card m-3 text-bg-secondary">
<div class="card-body">{{ msg }}</div> <div class="card-body">{{ msg.username }}: {{ msg.message }}</div>
</div> </div>
<!-- <!--
<div v-for="msg in msgs" class="input-group"> <div v-for="msg in msgs" class="input-group">
<div class="alert alert-primary">User</div> <div class="alert alert-primary">{{ msg.username }}</div>
<div class="alert alert-secondary">{{ msg }}</div> <div class="alert alert-secondary">{{ msg.message }}</div>
</div> </div>
--> -->
<form onsubmit="event.preventDefault();" class="container-fluid fixed-bottom mb-3"> <form onsubmit="event.preventDefault();" class="container-fluid fixed-bottom mb-3">

View File

@ -15,6 +15,7 @@ use poem_openapi::{
ApiResponse, Object, OpenApi, OpenApiService, Tags, ApiResponse, Object, OpenApi, OpenApiService, Tags,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json;
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
use tokio::sync::broadcast::Sender; use tokio::sync::broadcast::Sender;
@ -124,7 +125,13 @@ impl Api {
tokio::spawn(async move { tokio::spawn(async move {
while let Some(Ok(msg)) = stream.next().await { while let Some(Ok(msg)) = stream.next().await {
if let Message::Text(text) = msg { if let Message::Text(text) = msg {
if sender.send(format!("{name}: {text}")).is_err() { if sender
.send(ChatMsg {
username: name.clone(),
message: text,
})
.is_err()
{
break; break;
} }
} }
@ -133,7 +140,11 @@ impl Api {
tokio::spawn(async move { tokio::spawn(async move {
while let Ok(msg) = receiver.recv().await { while let Ok(msg) = receiver.recv().await {
if sink.send(Message::Text(msg)).await.is_err() { if sink
.send(Message::Text(serde_json::to_string(&msg).unwrap()))
.await
.is_err()
{
break; break;
} }
} }
@ -240,9 +251,15 @@ impl Api {
} }
} }
#[derive(Serialize, Deserialize, Clone)]
struct ChatMsg {
username: String,
message: String,
}
struct Api { struct Api {
db: Pool<Sqlite>, db: Pool<Sqlite>,
channel: Sender<String>, channel: Sender<ChatMsg>,
signup_open: bool, //TODO Should be in the db so it can change without restart signup_open: bool, //TODO Should be in the db so it can change without restart
} }
@ -255,7 +272,7 @@ async fn main() -> anyhow::Result<()> {
let session = ServerSession::new(CookieConfig::default(), MemoryStorage::new()); let session = ServerSession::new(CookieConfig::default(), MemoryStorage::new());
let channel = tokio::sync::broadcast::channel::<String>(128).0; let channel = tokio::sync::broadcast::channel::<ChatMsg>(128).0;
let dbpool = Pool::<Sqlite>::connect("sqlite:chat.db").await?; let dbpool = Pool::<Sqlite>::connect("sqlite:chat.db").await?;
let api = OpenApiService::new( let api = OpenApiService::new(