From 5c07c8368dc4d4ec24b3a74fc1d5475d65236345 Mon Sep 17 00:00:00 2001 From: Nikita Vilunov Date: Fri, 18 Aug 2023 16:45:48 +0200 Subject: [PATCH] persistence of chat messages --- docs/cheatsheet.md | 19 +++++++++++++++++++ src/core/repo/mod.rs | 21 +++++++++++++++++++-- src/core/room.rs | 17 +++++++++++++---- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/docs/cheatsheet.md b/docs/cheatsheet.md index 2097d9c..c74f8c0 100644 --- a/docs/cheatsheet.md +++ b/docs/cheatsheet.md @@ -30,3 +30,22 @@ Make sure `xmpp.key` starts and ends with: XMPP XSDs - [https://xmpp.org/schemas/index.shtml] IRC modern spec - [https://modern.ircdocs.horse/] + +## Initializing DB with some users + + sqlite3 db.sqlite < test/init_state.sql + +Same test migration could be used for integration tests in the future. + +## Using irssi + +irssi in a TUI-based IRC client. + +Connecting: + + /connect -nocap
[ [ []]] + +Password should be the same as in storage. +Example: + + /connect -nocap 127.0.0.1 6667 parolchik1 kek \ No newline at end of file diff --git a/src/core/repo/mod.rs b/src/core/repo/mod.rs index 48eb652..4041791 100644 --- a/src/core/repo/mod.rs +++ b/src/core/repo/mod.rs @@ -61,9 +61,9 @@ impl Storage { Ok(res) } - pub async fn create_new_room(&mut self, name: &str, topic: &str) -> Result<()> { + pub async fn create_new_room(&mut self, name: &str, topic: &str) -> Result { let mut executor = self.conn.lock().await; - let _: (u32,) = sqlx::query_as( + let (id,): (u32,) = sqlx::query_as( "insert into rooms(name, topic) values (?, ?) returning id;", @@ -73,6 +73,23 @@ impl Storage { .fetch_one(&mut *executor) .await?; + Ok(id) + } + + pub async fn insert_message(&mut self, room_id: u32, id: u32, content: &str) -> Result<()> { + let mut executor = self.conn.lock().await; + let (_,): (u32,) = sqlx::query_as( + "insert into messages(room_id, id, content) + values (?, ?, ?); + update rooms set message_count = message_count + 1 where id = ?;", + ) + .bind(room_id) + .bind(id) + .bind(content) + .bind(room_id) + .fetch_one(&mut *executor) + .await?; + Ok(()) } diff --git a/src/core/room.rs b/src/core/room.rs index b658be2..352c2ea 100644 --- a/src/core/room.rs +++ b/src/core/room.rs @@ -63,10 +63,12 @@ impl RoomRegistry { // room exists, but was not loaded log::debug!("Loading room {}...", &room_id.0); let room = Room { + storage_id: stored_room.id, room_id: room_id.clone(), - subscriptions: HashMap::new(), + subscriptions: HashMap::new(), // TODO figure out how to populate subscriptions topic: stored_room.topic.into(), message_count: stored_room.message_count, + storage: inner.storage.clone(), }; let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room))); inner.rooms.insert(room_id, room_handle.clone()); @@ -76,12 +78,14 @@ impl RoomRegistry { // room does not exist, create it and load log::debug!("Creating room {}...", &room_id.0); let topic = "New room"; - let _ = inner.storage.create_new_room(&*room_id.0, &*topic).await?; + let id = inner.storage.create_new_room(&*room_id.0, &*topic).await?; let room = Room { + storage_id: id, room_id: room_id.clone(), subscriptions: HashMap::new(), topic: topic.into(), message_count: 0, + storage: inner.storage.clone(), }; let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room))); inner.rooms.insert(room_id, room_handle.clone()); @@ -135,7 +139,7 @@ impl RoomHandle { } pub async fn send_message(&self, player_id: PlayerId, body: Str) { - let lock = self.0.read().await; + let mut lock = self.0.write().await; lock.send_message(player_id, body).await; } @@ -164,10 +168,12 @@ impl RoomHandle { } struct Room { + storage_id: u32, room_id: RoomId, subscriptions: HashMap, message_count: u32, topic: Str, + storage: Storage, } impl Room { async fn add_subscriber(&mut self, player_id: PlayerId, player_handle: PlayerHandle) { @@ -180,14 +186,17 @@ impl Room { self.broadcast_update(update, &player_id).await; } - async fn send_message(&self, author_id: PlayerId, body: Str) { + async fn send_message(&mut self, author_id: PlayerId, body: Str) -> Result<()> { tracing::info!("Adding a message to room"); + self.storage.insert_message(self.storage_id, self.message_count, &body).await?; + self.message_count += 1; let update = Updates::NewMessage { room_id: self.room_id.clone(), author_id: author_id.clone(), body, }; self.broadcast_update(update, &author_id).await; + Ok(()) } async fn broadcast_update(&self, update: Updates, except: &PlayerId) {