forked from lavina/lavina
1
0
Fork 0

persistence of chat messages

This commit is contained in:
Nikita Vilunov 2023-08-18 16:45:48 +02:00
parent f401aa786e
commit 5c07c8368d
3 changed files with 51 additions and 6 deletions

View File

@ -30,3 +30,22 @@ Make sure `xmpp.key` starts and ends with:
XMPP XSDs - [https://xmpp.org/schemas/index.shtml] XMPP XSDs - [https://xmpp.org/schemas/index.shtml]
IRC modern spec - [https://modern.ircdocs.horse/] 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 <address> [<port> [<password> [<nick>]]]
Password should be the same as in storage.
Example:
/connect -nocap 127.0.0.1 6667 parolchik1 kek

View File

@ -61,9 +61,9 @@ impl Storage {
Ok(res) 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<u32> {
let mut executor = self.conn.lock().await; let mut executor = self.conn.lock().await;
let _: (u32,) = sqlx::query_as( let (id,): (u32,) = sqlx::query_as(
"insert into rooms(name, topic) "insert into rooms(name, topic)
values (?, ?) values (?, ?)
returning id;", returning id;",
@ -73,6 +73,23 @@ impl Storage {
.fetch_one(&mut *executor) .fetch_one(&mut *executor)
.await?; .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(()) Ok(())
} }

View File

@ -63,10 +63,12 @@ impl RoomRegistry {
// room exists, but was not loaded // room exists, but was not loaded
log::debug!("Loading room {}...", &room_id.0); log::debug!("Loading room {}...", &room_id.0);
let room = Room { let room = Room {
storage_id: stored_room.id,
room_id: room_id.clone(), room_id: room_id.clone(),
subscriptions: HashMap::new(), subscriptions: HashMap::new(), // TODO figure out how to populate subscriptions
topic: stored_room.topic.into(), topic: stored_room.topic.into(),
message_count: stored_room.message_count, message_count: stored_room.message_count,
storage: inner.storage.clone(),
}; };
let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room))); let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room)));
inner.rooms.insert(room_id, room_handle.clone()); inner.rooms.insert(room_id, room_handle.clone());
@ -76,12 +78,14 @@ impl RoomRegistry {
// room does not exist, create it and load // room does not exist, create it and load
log::debug!("Creating room {}...", &room_id.0); log::debug!("Creating room {}...", &room_id.0);
let topic = "New room"; 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 { let room = Room {
storage_id: id,
room_id: room_id.clone(), room_id: room_id.clone(),
subscriptions: HashMap::new(), subscriptions: HashMap::new(),
topic: topic.into(), topic: topic.into(),
message_count: 0, message_count: 0,
storage: inner.storage.clone(),
}; };
let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room))); let room_handle = RoomHandle(Arc::new(AsyncRwLock::new(room)));
inner.rooms.insert(room_id, room_handle.clone()); 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) { 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; lock.send_message(player_id, body).await;
} }
@ -164,10 +168,12 @@ impl RoomHandle {
} }
struct Room { struct Room {
storage_id: u32,
room_id: RoomId, room_id: RoomId,
subscriptions: HashMap<PlayerId, PlayerHandle>, subscriptions: HashMap<PlayerId, PlayerHandle>,
message_count: u32, message_count: u32,
topic: Str, topic: Str,
storage: Storage,
} }
impl Room { impl Room {
async fn add_subscriber(&mut self, player_id: PlayerId, player_handle: PlayerHandle) { 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; 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"); 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 { let update = Updates::NewMessage {
room_id: self.room_id.clone(), room_id: self.room_id.clone(),
author_id: author_id.clone(), author_id: author_id.clone(),
body, body,
}; };
self.broadcast_update(update, &author_id).await; self.broadcast_update(update, &author_id).await;
Ok(())
} }
async fn broadcast_update(&self, update: Updates, except: &PlayerId) { async fn broadcast_update(&self, update: Updates, except: &PlayerId) {