feat: knocking
You may notice that we do no database migration for populating the state cache for knocking. This is because that in all the places where we use the state cache, it doesn't make a difference: - For local users, the clients wouldn't have been able to knock on rooms, as the `/knock` endpoint wasn't implemented yet, and I am not aware of any client which tries to knock over `/state`, as it would fail if the server is not currently in the room - It is not used for remote users
This commit is contained in:
@@ -27,6 +27,8 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||
self.roomuserid_joined.insert(&roomuser_id, &[])?;
|
||||
self.userroomid_invitestate.remove(&userroom_id)?;
|
||||
self.roomuserid_invitecount.remove(&roomuser_id)?;
|
||||
self.userroomid_knockstate.remove(&userroom_id)?;
|
||||
self.roomuserid_knockcount.remove(&roomuser_id)?;
|
||||
self.userroomid_leftstate.remove(&userroom_id)?;
|
||||
self.roomuserid_leftcount.remove(&roomuser_id)?;
|
||||
|
||||
@@ -52,12 +54,40 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||
)?;
|
||||
self.userroomid_joined.remove(&userroom_id)?;
|
||||
self.roomuserid_joined.remove(&roomuser_id)?;
|
||||
self.userroomid_knockstate.remove(&userroom_id)?;
|
||||
self.roomuserid_knockcount.remove(&roomuser_id)?;
|
||||
self.userroomid_leftstate.remove(&userroom_id)?;
|
||||
self.roomuserid_leftcount.remove(&roomuser_id)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mark_as_knocked(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
|
||||
) -> Result<()> {
|
||||
let (roomuser_id, userroom_id) = get_room_and_user_byte_ids(room_id, user_id);
|
||||
|
||||
self.userroomid_knockstate.insert(
|
||||
&userroom_id,
|
||||
&serde_json::to_vec(&last_state.unwrap_or_default())
|
||||
.expect("state to bytes always works"),
|
||||
)?;
|
||||
self.roomuserid_knockcount.insert(
|
||||
&roomuser_id,
|
||||
&services().globals.next_count()?.to_be_bytes(),
|
||||
)?;
|
||||
self.userroomid_joined.remove(&userroom_id)?;
|
||||
self.roomuserid_joined.remove(&roomuser_id)?;
|
||||
self.userroomid_invitestate.remove(&userroom_id)?;
|
||||
self.roomuserid_invitecount.remove(&roomuser_id)?;
|
||||
self.userroomid_leftstate.remove(&userroom_id)?;
|
||||
self.roomuserid_leftcount.remove(&roomuser_id)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mark_as_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
let (roomuser_id, userroom_id) = get_room_and_user_byte_ids(room_id, user_id);
|
||||
@@ -74,6 +104,8 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||
self.roomuserid_joined.remove(&roomuser_id)?;
|
||||
self.userroomid_invitestate.remove(&userroom_id)?;
|
||||
self.roomuserid_invitecount.remove(&roomuser_id)?;
|
||||
self.userroomid_knockstate.remove(&userroom_id)?;
|
||||
self.roomuserid_knockcount.remove(&roomuser_id)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -390,6 +422,21 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn get_knock_count(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
|
||||
let mut key = room_id.as_bytes().to_vec();
|
||||
key.push(0xff);
|
||||
key.extend_from_slice(user_id.as_bytes());
|
||||
|
||||
self.roomuserid_knockcount
|
||||
.get(&key)?
|
||||
.map_or(Ok(None), |bytes| {
|
||||
Ok(Some(utils::u64_from_bytes(&bytes).map_err(|_| {
|
||||
Error::bad_database("Invalid knockcount in db.")
|
||||
})?))
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn get_left_count(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
|
||||
let mut key = room_id.as_bytes().to_vec();
|
||||
@@ -440,6 +487,16 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||
scan_userroom_id_memberstate_tree(user_id, &self.userroomid_invitestate)
|
||||
}
|
||||
|
||||
/// Returns an iterator over all rooms a user has knocked on.
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn rooms_knocked<'a>(
|
||||
&'a self,
|
||||
user_id: &UserId,
|
||||
) -> Box<dyn Iterator<Item = Result<(OwnedRoomId, Vec<Raw<AnyStrippedStateEvent>>)>> + 'a> {
|
||||
scan_userroom_id_memberstate_tree(user_id, &self.userroomid_knockstate)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn invite_state(
|
||||
&self,
|
||||
@@ -461,6 +518,27 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||
.transpose()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn knock_state(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
|
||||
let mut key = user_id.as_bytes().to_vec();
|
||||
key.push(0xff);
|
||||
key.extend_from_slice(room_id.as_bytes());
|
||||
|
||||
self.userroomid_knockstate
|
||||
.get(&key)?
|
||||
.map(|state| {
|
||||
let state = serde_json::from_slice(&state)
|
||||
.map_err(|_| Error::bad_database("Invalid state in userroomid_knockstate."))?;
|
||||
|
||||
Ok(state)
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn left_state(
|
||||
&self,
|
||||
|
||||
@@ -99,6 +99,8 @@ pub struct KeyValueDatabase {
|
||||
pub(super) roomuseroncejoinedids: Arc<dyn KvTree>,
|
||||
pub(super) userroomid_invitestate: Arc<dyn KvTree>, // InviteState = Vec<Raw<AnyStrippedStateEvent>>
|
||||
pub(super) roomuserid_invitecount: Arc<dyn KvTree>, // InviteCount = Count
|
||||
pub(super) userroomid_knockstate: Arc<dyn KvTree>, // KnockState = Vec<Raw<AnyStrippedStateEvent>>
|
||||
pub(super) roomuserid_knockcount: Arc<dyn KvTree>, // KnockCount = Count
|
||||
pub(super) userroomid_leftstate: Arc<dyn KvTree>,
|
||||
pub(super) roomuserid_leftcount: Arc<dyn KvTree>,
|
||||
|
||||
@@ -313,6 +315,8 @@ impl KeyValueDatabase {
|
||||
roomuseroncejoinedids: builder.open_tree("roomuseroncejoinedids")?,
|
||||
userroomid_invitestate: builder.open_tree("userroomid_invitestate")?,
|
||||
roomuserid_invitecount: builder.open_tree("roomuserid_invitecount")?,
|
||||
userroomid_knockstate: builder.open_tree("userroomid_knockstate")?,
|
||||
roomuserid_knockcount: builder.open_tree("roomuserid_knockcount")?,
|
||||
userroomid_leftstate: builder.open_tree("userroomid_leftstate")?,
|
||||
roomuserid_leftcount: builder.open_tree("roomuserid_leftcount")?,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user