Room State Management #44

Manually merged
projectmoon merged 11 commits from room-state-management into master 2020-11-10 20:58:50 +00:00
2 changed files with 72 additions and 10 deletions
Showing only changes of commit d7aaed9e00 - Show all commits

View File

@ -100,13 +100,13 @@ impl EventEmitter for DiceBot {
let (room_id, username) = (room.room_id.as_str(), &room_member.state_key);
let result = if event_affects_us && !adding_user {
debug!("Clearing all information for room ID {}", room_id);
info!("Clearing all information for room ID {}", room_id);
self.db.rooms.clear_info(room_id)
} else if !event_affects_us && adding_user {
debug!("Adding {} to room ID {}", username, room_id);
info!("Adding user {} to room ID {}", username, room_id);
self.db.rooms.add_user_to_room(username, room_id)
} else if !event_affects_us && !adding_user {
debug!("Removing {} from room ID {}", username, room_id);
info!("Removing user {} from room ID {}", username, room_id);
self.db.rooms.remove_user_from_room(username, room_id)
} else {
debug!("Ignoring a room member event: {:#?}", room_member);

View File

@ -17,6 +17,7 @@ pub struct Rooms {
pub(in crate::db) username_roomids: Tree,
}
#[derive(Clone, Copy)]
enum TxableTree<'a> {
Tree(&'a Tree),
Tx(&'a TransactionalTree),
@ -45,6 +46,17 @@ fn get_set<'a, T: Into<TxableTree<'a>>>(tree: T, key: &[u8]) -> Result<HashSet<S
Ok(set)
}
fn remove_from_set<'a, T: Into<TxableTree<'a>> + Copy>(
tree: T,
key: &[u8],
value_to_remove: &str,
) -> Result<(), DataError> {
let mut set = get_set(tree, key)?;
set.remove(value_to_remove);
insert_set(tree, key, set)?;
Ok(())
}
fn insert_set<'a, T: Into<TxableTree<'a>>>(
tree: T,
key: &[u8],
@ -115,13 +127,25 @@ impl Rooms {
Ok(())
}
pub fn clear_info(&self, _room_id: &str) -> Result<(), DataError> {
//TODO implement me
//when bot leaves a room, it must, atomically:
// - delete roominfo struct from room info tree.
// - load list of users it knows about in room.
// - remove room id from every user's list. (cannot reuse existing fn because atomicity)
// - delete list of users in room from tree.
pub fn clear_info(&self, room_id: &str) -> Result<(), DataError> {
(&self.username_roomids, &self.roomid_usernames).transaction(
|(tx_username_roomids, tx_roomid_usernames)| {
let roomid_key = room_id.as_bytes();
let users_in_room = get_set(tx_roomid_usernames, roomid_key)?;
//Remove the room ID from every user's room ID list.
for username in users_in_room {
remove_from_set(tx_username_roomids, username.as_bytes(), room_id)?;
}
//Remove this room entry for the room ID -> username tree.
tx_roomid_usernames.remove(roomid_key)?;
//TODO: delete roominfo struct from room info tree.
Ok(())
},
)?;
Ok(())
}
}
@ -184,4 +208,42 @@ mod tests {
assert_eq!(HashSet::new(), users_in_room);
assert_eq!(HashSet::new(), rooms_for_user);
}
#[test]
fn clear_info() {
let rooms = create_test_instance();
rooms
.add_user_to_room("testuser", "myroom1")
.expect("Could not add user to room1");
rooms
.add_user_to_room("testuser", "myroom2")
.expect("Could not add user to room2");
rooms
.clear_info("myroom1")
.expect("Could not clear room info");
let users_in_room1 = rooms
.get_users_in_room("myroom1")
.expect("Could not retrieve users in room1");
let users_in_room2 = rooms
.get_users_in_room("myroom2")
.expect("Could not retrieve users in room2");
let rooms_for_user = rooms
.get_rooms_for_user("testuser")
.expect("Could not get rooms for user");
let expected_users_in_room2: HashSet<String> =
vec![String::from("testuser")].into_iter().collect();
let expected_rooms_for_user: HashSet<String> =
vec![String::from("myroom2")].into_iter().collect();
assert_eq!(HashSet::new(), users_in_room1);
assert_eq!(expected_users_in_room2, users_in_room2);
assert_eq!(expected_rooms_for_user, rooms_for_user);
}
}