forked from projectmoon/tenebrous-dicebot
Remove most of Room DB API
This commit is contained in:
parent
97be5d5ccb
commit
849a1b6a14
|
@ -2,9 +2,7 @@ use crate::error::BotError;
|
||||||
use crate::models::User;
|
use crate::models::User;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use errors::DataError;
|
use errors::DataError;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::models::RoomInfo;
|
|
||||||
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod sqlite;
|
pub mod sqlite;
|
||||||
|
@ -34,20 +32,6 @@ pub(crate) trait Users {
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub(crate) trait Rooms {
|
pub(crate) trait Rooms {
|
||||||
async fn should_process(&self, room_id: &str, event_id: &str) -> Result<bool, DataError>;
|
async fn should_process(&self, room_id: &str, event_id: &str) -> Result<bool, DataError>;
|
||||||
|
|
||||||
async fn insert_room_info(&self, info: &RoomInfo) -> Result<(), DataError>;
|
|
||||||
|
|
||||||
async fn get_room_info(&self, room_id: &str) -> Result<Option<RoomInfo>, DataError>;
|
|
||||||
|
|
||||||
async fn get_rooms_for_user(&self, user_id: &str) -> Result<HashSet<String>, DataError>;
|
|
||||||
|
|
||||||
async fn get_users_in_room(&self, room_id: &str) -> Result<HashSet<String>, DataError>;
|
|
||||||
|
|
||||||
async fn add_user_to_room(&self, username: &str, room_id: &str) -> Result<(), DataError>;
|
|
||||||
|
|
||||||
async fn remove_user_from_room(&self, username: &str, room_id: &str) -> Result<(), DataError>;
|
|
||||||
|
|
||||||
async fn clear_info(&self, room_id: &str) -> Result<(), DataError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move this up to the top once we delete sled. Traits will be the
|
// TODO move this up to the top once we delete sled. Traits will be the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use barrel::backend::Sqlite;
|
use barrel::backend::Sqlite;
|
||||||
use barrel::{types, Migration};
|
use barrel::Migration;
|
||||||
|
|
||||||
pub fn migration() -> String {
|
pub fn migration() -> String {
|
||||||
let mut m = Migration::new();
|
let mut m = Migration::new();
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use super::Database;
|
use super::Database;
|
||||||
use crate::db::{errors::DataError, Rooms};
|
use crate::db::{errors::DataError, Rooms};
|
||||||
use crate::models::RoomInfo;
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
async fn record_event(conn: &SqlitePool, room_id: &str, event_id: &str) -> Result<(), DataError> {
|
async fn record_event(conn: &SqlitePool, room_id: &str, event_id: &str) -> Result<(), DataError> {
|
||||||
|
@ -49,106 +47,10 @@ impl Rooms for Database {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn insert_room_info(&self, info: &RoomInfo) -> Result<(), DataError> {
|
|
||||||
sqlx::query(
|
|
||||||
r#"INSERT INTO room_info (room_id, room_name) VALUES (?, ?)
|
|
||||||
ON CONFLICT(room_id) DO UPDATE SET room_name = ?"#,
|
|
||||||
)
|
|
||||||
.bind(&info.room_id)
|
|
||||||
.bind(&info.room_name)
|
|
||||||
.bind(&info.room_name)
|
|
||||||
.execute(&self.conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_room_info(&self, room_id: &str) -> Result<Option<RoomInfo>, DataError> {
|
|
||||||
let info = sqlx::query!(
|
|
||||||
r#"SELECT room_id, room_name FROM room_info
|
|
||||||
WHERE room_id = ?"#,
|
|
||||||
room_id
|
|
||||||
)
|
|
||||||
.fetch_optional(&self.conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(info.map(|i| RoomInfo {
|
|
||||||
room_id: i.room_id,
|
|
||||||
room_name: i.room_name,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_rooms_for_user(&self, user_id: &str) -> Result<HashSet<String>, DataError> {
|
|
||||||
let room_ids = sqlx::query!(
|
|
||||||
r#"SELECT room_id FROM room_users
|
|
||||||
WHERE username = ?"#,
|
|
||||||
user_id
|
|
||||||
)
|
|
||||||
.fetch_all(&self.conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(room_ids.into_iter().map(|row| row.room_id).collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_users_in_room(&self, room_id: &str) -> Result<HashSet<String>, DataError> {
|
|
||||||
let usernames = sqlx::query!(
|
|
||||||
r#"SELECT username FROM room_users
|
|
||||||
WHERE room_id = ?"#,
|
|
||||||
room_id
|
|
||||||
)
|
|
||||||
.fetch_all(&self.conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(usernames.into_iter().map(|row| row.username).collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn add_user_to_room(&self, username: &str, room_id: &str) -> Result<(), DataError> {
|
|
||||||
sqlx::query(
|
|
||||||
"INSERT INTO room_users (room_id, username) VALUES (?, ?)
|
|
||||||
ON CONFLICT DO NOTHING",
|
|
||||||
)
|
|
||||||
.bind(room_id)
|
|
||||||
.bind(username)
|
|
||||||
.execute(&self.conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn remove_user_from_room(&self, username: &str, room_id: &str) -> Result<(), DataError> {
|
|
||||||
sqlx::query("DELETE FROM room_users where username = ? AND room_id = ?")
|
|
||||||
.bind(username)
|
|
||||||
.bind(room_id)
|
|
||||||
.execute(&self.conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn clear_info(&self, room_id: &str) -> Result<(), DataError> {
|
|
||||||
// We do not clear event history here, because if we rejoin a
|
|
||||||
// room, we would re-process events we've already seen.
|
|
||||||
let mut tx = self.conn.begin().await?;
|
|
||||||
|
|
||||||
sqlx::query("DELETE FROM room_info where room_id = ?")
|
|
||||||
.bind(room_id)
|
|
||||||
.execute(&mut tx)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
sqlx::query("DELETE FROM room_users where room_id = ?")
|
|
||||||
.bind(room_id)
|
|
||||||
.execute(&mut tx)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
tx.commit().await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
use crate::db::sqlite::Database;
|
use crate::db::sqlite::Database;
|
||||||
use crate::db::Rooms;
|
use crate::db::Rooms;
|
||||||
|
|
||||||
|
@ -181,200 +83,4 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(second_check, false);
|
assert_eq!(second_check, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
||||||
async fn insert_and_get_room_info_test() {
|
|
||||||
let db = create_db().await;
|
|
||||||
|
|
||||||
let info = RoomInfo {
|
|
||||||
room_id: "myroomid".to_string(),
|
|
||||||
room_name: "myroomname".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
db.insert_room_info(&info)
|
|
||||||
.await
|
|
||||||
.expect("Could not insert room info.");
|
|
||||||
|
|
||||||
let retrieved_info = db
|
|
||||||
.get_room_info("myroomid")
|
|
||||||
.await
|
|
||||||
.expect("Could not retrieve room info.");
|
|
||||||
|
|
||||||
assert!(retrieved_info.is_some());
|
|
||||||
assert_eq!(info, retrieved_info.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
||||||
async fn insert_room_info_updates_existing() {
|
|
||||||
let db = create_db().await;
|
|
||||||
|
|
||||||
let info1 = RoomInfo {
|
|
||||||
room_id: "myroomid".to_string(),
|
|
||||||
room_name: "myroomname".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
db.insert_room_info(&info1)
|
|
||||||
.await
|
|
||||||
.expect("Could not insert room info1.");
|
|
||||||
|
|
||||||
let info2 = RoomInfo {
|
|
||||||
room_id: "myroomid".to_string(),
|
|
||||||
room_name: "myroomname2".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
db.insert_room_info(&info2)
|
|
||||||
.await
|
|
||||||
.expect("Could not update room info after first insert");
|
|
||||||
|
|
||||||
let retrieved_info = db
|
|
||||||
.get_room_info("myroomid")
|
|
||||||
.await
|
|
||||||
.expect("Could not get room info");
|
|
||||||
|
|
||||||
assert!(retrieved_info.is_some());
|
|
||||||
let retrieved_info = retrieved_info.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(retrieved_info.room_id, "myroomid");
|
|
||||||
assert_eq!(retrieved_info.room_name, "myroomname2");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
||||||
async fn add_user_to_room_test() {
|
|
||||||
let db = create_db().await;
|
|
||||||
|
|
||||||
db.add_user_to_room("myuser", "myroom")
|
|
||||||
.await
|
|
||||||
.expect("Could not add user to room.");
|
|
||||||
|
|
||||||
let users_in_room = db
|
|
||||||
.get_users_in_room("myroom")
|
|
||||||
.await
|
|
||||||
.expect("Could not get users in room.");
|
|
||||||
|
|
||||||
assert_eq!(users_in_room.len(), 1);
|
|
||||||
assert!(users_in_room.contains("myuser"));
|
|
||||||
|
|
||||||
let rooms_for_user = db
|
|
||||||
.get_rooms_for_user("myuser")
|
|
||||||
.await
|
|
||||||
.expect("Could not get rooms for user");
|
|
||||||
|
|
||||||
assert_eq!(rooms_for_user.len(), 1);
|
|
||||||
assert!(rooms_for_user.contains("myroom"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
||||||
async fn add_user_to_room_does_not_have_constraint_violation() {
|
|
||||||
let db = create_db().await;
|
|
||||||
|
|
||||||
db.add_user_to_room("myuser", "myroom")
|
|
||||||
.await
|
|
||||||
.expect("Could not add user to room.");
|
|
||||||
|
|
||||||
let second_attempt = db.add_user_to_room("myuser", "myroom").await;
|
|
||||||
|
|
||||||
assert!(second_attempt.is_ok());
|
|
||||||
|
|
||||||
let users_in_room = db
|
|
||||||
.get_users_in_room("myroom")
|
|
||||||
.await
|
|
||||||
.expect("Could not get users in room.");
|
|
||||||
|
|
||||||
assert_eq!(users_in_room.len(), 1);
|
|
||||||
assert!(users_in_room.contains("myuser"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
||||||
async fn remove_user_from_room_test() {
|
|
||||||
let db = create_db().await;
|
|
||||||
|
|
||||||
db.add_user_to_room("myuser", "myroom")
|
|
||||||
.await
|
|
||||||
.expect("Could not add user to room.");
|
|
||||||
|
|
||||||
let remove_attempt = db.remove_user_from_room("myuser", "myroom").await;
|
|
||||||
|
|
||||||
assert!(remove_attempt.is_ok());
|
|
||||||
|
|
||||||
let users_in_room = db
|
|
||||||
.get_users_in_room("myroom")
|
|
||||||
.await
|
|
||||||
.expect("Could not get users in room.");
|
|
||||||
|
|
||||||
assert_eq!(users_in_room.len(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
||||||
async fn clear_info_does_not_delete_other_rooms() {
|
|
||||||
let db = create_db().await;
|
|
||||||
|
|
||||||
let info1 = RoomInfo {
|
|
||||||
room_id: "myroomid".to_string(),
|
|
||||||
room_name: "myroomname".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let info2 = RoomInfo {
|
|
||||||
room_id: "myroomid2".to_string(),
|
|
||||||
room_name: "myroomname2".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
db.insert_room_info(&info1)
|
|
||||||
.await
|
|
||||||
.expect("Could not insert room info1.");
|
|
||||||
|
|
||||||
db.insert_room_info(&info2)
|
|
||||||
.await
|
|
||||||
.expect("Could not insert room info2.");
|
|
||||||
|
|
||||||
db.add_user_to_room("myuser", &info1.room_id)
|
|
||||||
.await
|
|
||||||
.expect("Could not add user to room.");
|
|
||||||
|
|
||||||
db.clear_info(&info1.room_id)
|
|
||||||
.await
|
|
||||||
.expect("Could not clear room info1");
|
|
||||||
|
|
||||||
let room_info2 = db
|
|
||||||
.get_room_info(&info2.room_id)
|
|
||||||
.await
|
|
||||||
.expect("Could not get room info2.");
|
|
||||||
|
|
||||||
assert!(room_info2.is_some());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
|
||||||
async fn clear_info_test() {
|
|
||||||
let db = create_db().await;
|
|
||||||
|
|
||||||
let info = RoomInfo {
|
|
||||||
room_id: "myroomid".to_string(),
|
|
||||||
room_name: "myroomname".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
db.insert_room_info(&info)
|
|
||||||
.await
|
|
||||||
.expect("Could not insert room info.");
|
|
||||||
|
|
||||||
db.add_user_to_room("myuser", &info.room_id)
|
|
||||||
.await
|
|
||||||
.expect("Could not add user to room.");
|
|
||||||
|
|
||||||
db.clear_info(&info.room_id)
|
|
||||||
.await
|
|
||||||
.expect("Could not clear room info");
|
|
||||||
|
|
||||||
let users_in_room = db
|
|
||||||
.get_users_in_room(&info.room_id)
|
|
||||||
.await
|
|
||||||
.expect("Could not get users in room.");
|
|
||||||
|
|
||||||
assert_eq!(users_in_room.len(), 0);
|
|
||||||
|
|
||||||
let room_info = db
|
|
||||||
.get_room_info(&info.room_id)
|
|
||||||
.await
|
|
||||||
.expect("Could not get room info.");
|
|
||||||
|
|
||||||
assert!(room_info.is_none());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue