Room State Management #44

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

View File

@ -11,9 +11,9 @@ use matrix_sdk::Error as MatrixError;
use matrix_sdk::{ use matrix_sdk::{
self, self,
events::{ events::{
room::member::MemberEventContent, room::member::{MemberEventContent, MembershipState},
room::message::{MessageEventContent, NoticeMessageEventContent, TextMessageEventContent}, room::message::{MessageEventContent, NoticeMessageEventContent, TextMessageEventContent},
AnyMessageEventContent, StrippedStateEvent, SyncMessageEvent, AnyMessageEventContent, StrippedStateEvent, SyncMessageEvent, SyncStateEvent,
}, },
Client, ClientConfig, EventEmitter, JsonStore, Room, SyncRoom, SyncSettings, Client, ClientConfig, EventEmitter, JsonStore, Room, SyncRoom, SyncSettings,
}; };
@ -229,6 +229,37 @@ async fn should_process<'a>(
/// Originally adapted from the matrix-rust-sdk examples. /// Originally adapted from the matrix-rust-sdk examples.
#[async_trait] #[async_trait]
impl EventEmitter for DiceBot { impl EventEmitter for DiceBot {
async fn on_room_member(
&self,
room: SyncRoom,
room_member: &SyncStateEvent<MemberEventContent>,
) {
//When joining a channel, we get join events from other users.
//content is MemberContent, and it has a membership type.
//Ignore if state_key is our username, because we only care about other users.
let event_affects_us = if let Some(our_user_id) = self.client.user_id().await {
room_member.state_key == our_user_id
} else {
false
};
let should_add = match room_member.content.membership {
MembershipState::Join => true,
MembershipState::Leave | MembershipState::Ban => false,
_ => return,
};
//if event affects us and is leave/ban, delete all our info.
//if event does not affect us, delete info only for that user.
//TODO replace with call to new db.rooms thing.
println!(
"member {} recorded with action {:?} to/from db.",
room_member.state_key, should_add
);
}
async fn on_stripped_state_member( async fn on_stripped_state_member(
&self, &self,
room: SyncRoom, room: SyncRoom,

View File

@ -1,5 +1,6 @@
use crate::db::errors::{DataError, MigrationError}; use crate::db::errors::{DataError, MigrationError};
use crate::db::migrations::{get_migration_version, Migrations}; use crate::db::migrations::{get_migration_version, Migrations};
use crate::db::rooms::Rooms;
use crate::db::variables::Variables; use crate::db::variables::Variables;
use log::info; use log::info;
use sled::{Config, Db}; use sled::{Config, Db};
@ -8,6 +9,7 @@ use std::path::Path;
pub mod data_migrations; pub mod data_migrations;
pub mod errors; pub mod errors;
pub mod migrations; pub mod migrations;
pub mod rooms;
pub mod schema; pub mod schema;
pub mod variables; pub mod variables;
@ -16,6 +18,7 @@ pub struct Database {
db: Db, db: Db,
pub(crate) variables: Variables, pub(crate) variables: Variables,
pub(crate) migrations: Migrations, pub(crate) migrations: Migrations,
pub(crate) rooms: Rooms,
} }
impl Database { impl Database {
@ -26,6 +29,7 @@ impl Database {
db: db.clone(), db: db.clone(),
variables: Variables::new(&db)?, variables: Variables::new(&db)?,
migrations: Migrations(migrations), migrations: Migrations(migrations),
rooms: Rooms::new(&db)?,
}) })
} }

82
src/db/rooms.rs Normal file
View File

@ -0,0 +1,82 @@
use crate::db::errors::DataError;
use crate::db::schema::convert_i32;
use byteorder::LittleEndian;
use sled::transaction::{abort, TransactionalTree};
use sled::Transactional;
use sled::Tree;
use std::collections::HashMap;
use std::collections::HashSet;
use std::convert::From;
use std::str;
use zerocopy::byteorder::I32;
use zerocopy::AsBytes;
#[derive(Clone)]
pub struct Rooms {
/// Room ID -> RoomInfo struct (single entries)
pub(in crate::db) roomid_roominfo: Tree,
/// Room ID -> list of usernames in room.
pub(in crate::db) roomid_usernames: Tree,
/// Username -> list of room IDs user is in.
pub(in crate::db) username_roomids: Tree,
}
// /// Request soemthing by a username and room ID.
// pub struct UserAndRoom<'a>(pub &'a str, pub &'a str);
// fn to_vec(value: &UserAndRoom<'_>) -> Vec<u8> {
// let mut bytes = vec![];
// bytes.extend_from_slice(value.0.as_bytes());
// bytes.push(0xfe);
// bytes.extend_from_slice(value.1.as_bytes());
// bytes
// }
// impl From<UserAndRoom<'_>> for Vec<u8> {
// fn from(value: UserAndRoom) -> Vec<u8> {
// to_vec(&value)
// }
// }
// impl From<&UserAndRoom<'_>> for Vec<u8> {
// fn from(value: &UserAndRoom) -> Vec<u8> {
// to_vec(value)
// }
// }
impl Rooms {
pub(in crate::db) fn new(db: &sled::Db) -> Result<Rooms, sled::Error> {
Ok(Rooms {
roomid_roominfo: db.open_tree("roomid_roominfo")?,
roomid_usernames: db.open_tree("roomid_usernames")?,
username_roomids: db.open_tree("username_roomids")?,
})
}
pub fn add_user_to_room(&self, username: &str, room_id: &str) -> Result<(), DataError> {
//in txn:
//get or create list of users in room
//get or create list of rooms user is in
//deserialize/create set and add username to set for roomid
//deserialize/create set and add roomid to set for username
//store both again
projectmoon marked this conversation as resolved
Review

Perhaps move this and TxableTree into a common part of the database code. Maybe also convert it to a trait. The atomicity issues with Tree instances also should be addressed. Use fetch_and_update when it's a regular Tree, and the existing code if it's a TransactionalTree (since the atomicity is controlled by the transaction).

Perhaps move this and `TxableTree` into a common part of the database code. Maybe also convert it to a trait. The atomicity issues with `Tree` instances also should be addressed. Use `fetch_and_update` when it's a regular Tree, and the existing code if it's a `TransactionalTree` (since the atomicity is controlled by the transaction).
Review

Deferring to a future changeset.

Deferring to a future changeset.
let user_to_rooms: HashSet<String> = self
.username_roomids
.get(username.as_bytes())?
.map(|bytes| bincode::deserialize::<HashSet<String>>(&bytes))
.unwrap_or(Ok(HashSet::new()))?;
let room_to_users: HashSet<String> = self
.roomid_usernames
.get(room_id.as_bytes())?
.map(|bytes| bincode::deserialize::<HashSet<String>>(&bytes))
.unwrap_or(Ok(HashSet::new()))?;
Ok(())
}
pub fn remove_user_from_room(&self, username: &str, room_id: &str) -> Result<(), DataError> {
Ok(())
}
}