perf(knock): add database cache
This commit is contained in:
parent
1f313c6807
commit
ae0fa29b09
4 changed files with 116 additions and 1 deletions
|
@ -66,6 +66,8 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||||
self.roomuserid_joined.remove(&roomuser_id)?;
|
self.roomuserid_joined.remove(&roomuser_id)?;
|
||||||
self.userroomid_leftstate.remove(&userroom_id)?;
|
self.userroomid_leftstate.remove(&userroom_id)?;
|
||||||
self.roomuserid_leftcount.remove(&roomuser_id)?;
|
self.roomuserid_leftcount.remove(&roomuser_id)?;
|
||||||
|
self.userroomid_knockedstate.remove(&userroom_id)?;
|
||||||
|
self.roomuserid_knockedcount.remove(&roomuser_id)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -91,6 +93,36 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||||
self.roomuserid_joined.remove(&roomuser_id)?;
|
self.roomuserid_joined.remove(&roomuser_id)?;
|
||||||
self.userroomid_invitestate.remove(&userroom_id)?;
|
self.userroomid_invitestate.remove(&userroom_id)?;
|
||||||
self.roomuserid_invitecount.remove(&roomuser_id)?;
|
self.roomuserid_invitecount.remove(&roomuser_id)?;
|
||||||
|
self.userroomid_knockedstate.remove(&userroom_id)?;
|
||||||
|
self.roomuserid_knockedcount.remove(&roomuser_id)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_as_knocked(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||||
|
let mut roomuser_id = room_id.as_bytes().to_vec();
|
||||||
|
roomuser_id.push(0xff);
|
||||||
|
roomuser_id.extend_from_slice(user_id.as_bytes());
|
||||||
|
|
||||||
|
let mut userroom_id = user_id.as_bytes().to_vec();
|
||||||
|
userroom_id.push(0xff);
|
||||||
|
userroom_id.extend_from_slice(room_id.as_bytes());
|
||||||
|
|
||||||
|
self.userroomid_knockedstate.insert(
|
||||||
|
&userroom_id,
|
||||||
|
&serde_json::to_vec(&Vec::<Raw<AnySyncStateEvent>>::new())
|
||||||
|
.expect("state to bytes always works"),
|
||||||
|
)?;
|
||||||
|
self.roomuserid_knockedcount.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_invitestate.remove(&userroom_id)?;
|
||||||
|
self.roomuserid_invitecount.remove(&roomuser_id)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -604,4 +636,13 @@ impl service::rooms::state_cache::Data for KeyValueDatabase {
|
||||||
|
|
||||||
Ok(self.userroomid_leftstate.get(&userroom_id)?.is_some())
|
Ok(self.userroomid_leftstate.get(&userroom_id)?.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(self))]
|
||||||
|
fn is_knocked(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
|
||||||
|
let mut userroom_id = user_id.as_bytes().to_vec();
|
||||||
|
userroom_id.push(0xff);
|
||||||
|
userroom_id.extend_from_slice(room_id.as_bytes());
|
||||||
|
|
||||||
|
Ok(self.userroomid_knockedstate.get(&userroom_id)?.is_some())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,10 @@ use lru_cache::LruCache;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
events::{
|
events::{
|
||||||
push_rules::{PushRulesEvent, PushRulesEventContent},
|
push_rules::{PushRulesEvent, PushRulesEventContent},
|
||||||
room::message::RoomMessageEventContent,
|
room::{
|
||||||
|
member::{MembershipState, RoomMemberEventContent},
|
||||||
|
message::RoomMessageEventContent,
|
||||||
|
},
|
||||||
GlobalAccountDataEvent, GlobalAccountDataEventType, StateEventType,
|
GlobalAccountDataEvent, GlobalAccountDataEventType, StateEventType,
|
||||||
},
|
},
|
||||||
push::Ruleset,
|
push::Ruleset,
|
||||||
|
@ -100,6 +103,8 @@ pub struct KeyValueDatabase {
|
||||||
pub(super) roomuserid_invitecount: Arc<dyn KvTree>, // InviteCount = Count
|
pub(super) roomuserid_invitecount: Arc<dyn KvTree>, // InviteCount = Count
|
||||||
pub(super) userroomid_leftstate: Arc<dyn KvTree>,
|
pub(super) userroomid_leftstate: Arc<dyn KvTree>,
|
||||||
pub(super) roomuserid_leftcount: Arc<dyn KvTree>,
|
pub(super) roomuserid_leftcount: Arc<dyn KvTree>,
|
||||||
|
pub(super) userroomid_knockedstate: Arc<dyn KvTree>,
|
||||||
|
pub(super) roomuserid_knockedcount: Arc<dyn KvTree>,
|
||||||
|
|
||||||
pub(super) alias_userid: Arc<dyn KvTree>, // User who created the alias
|
pub(super) alias_userid: Arc<dyn KvTree>, // User who created the alias
|
||||||
|
|
||||||
|
@ -328,6 +333,8 @@ impl KeyValueDatabase {
|
||||||
roomuserid_invitecount: builder.open_tree("roomuserid_invitecount")?,
|
roomuserid_invitecount: builder.open_tree("roomuserid_invitecount")?,
|
||||||
userroomid_leftstate: builder.open_tree("userroomid_leftstate")?,
|
userroomid_leftstate: builder.open_tree("userroomid_leftstate")?,
|
||||||
roomuserid_leftcount: builder.open_tree("roomuserid_leftcount")?,
|
roomuserid_leftcount: builder.open_tree("roomuserid_leftcount")?,
|
||||||
|
userroomid_knockedstate: builder.open_tree("userroomid_knockedstate")?,
|
||||||
|
roomuserid_knockedcount: builder.open_tree("roomuserid_knockedcount")?,
|
||||||
|
|
||||||
alias_userid: builder.open_tree("alias_userid")?,
|
alias_userid: builder.open_tree("alias_userid")?,
|
||||||
|
|
||||||
|
@ -941,6 +948,60 @@ impl KeyValueDatabase {
|
||||||
warn!("Migration: 12 -> 13 finished");
|
warn!("Migration: 12 -> 13 finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if services().globals.database_version()? < 14 {
|
||||||
|
for username in services().users.list_local_users()? {
|
||||||
|
let user = match UserId::parse_with_server_name(
|
||||||
|
username.clone(),
|
||||||
|
services().globals.server_name(),
|
||||||
|
) {
|
||||||
|
Ok(u) => u,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Invalid username {username}: {e}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for room in
|
||||||
|
services()
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.iter_ids()
|
||||||
|
.filter_map(|room_id| match room_id {
|
||||||
|
Ok(room_id) => Some(room_id),
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Invalid room id: {e}");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if services()
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.room_state_get(&room, &StateEventType::RoomMember, user.as_str())?
|
||||||
|
.map(|pdu| {
|
||||||
|
serde_json::from_str(pdu.content.get())
|
||||||
|
.map_err(|_| Error::bad_database("Invalid PDU in database."))
|
||||||
|
})
|
||||||
|
.transpose()?
|
||||||
|
.map(|content: RoomMemberEventContent| content.membership)
|
||||||
|
== Some(MembershipState::Knock)
|
||||||
|
{
|
||||||
|
services().rooms.state_cache.update_membership(
|
||||||
|
&room,
|
||||||
|
&user,
|
||||||
|
MembershipState::Knock,
|
||||||
|
&user,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
services().globals.bump_database_version(14)?;
|
||||||
|
|
||||||
|
warn!("Migration: 13 -> 14 finished");
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
services().globals.database_version().unwrap(),
|
services().globals.database_version().unwrap(),
|
||||||
latest_database_version
|
latest_database_version
|
||||||
|
|
|
@ -18,6 +18,9 @@ pub trait Data: Send + Sync {
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
fn mark_as_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
fn mark_as_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||||
|
|
||||||
|
/// Marks a user as knocking on a room
|
||||||
|
fn mark_as_knocked(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||||
|
|
||||||
fn update_joined_count(&self, room_id: &RoomId) -> Result<()>;
|
fn update_joined_count(&self, room_id: &RoomId) -> Result<()>;
|
||||||
|
|
||||||
fn get_our_real_users(&self, room_id: &RoomId) -> Result<Arc<HashSet<OwnedUserId>>>;
|
fn get_our_real_users(&self, room_id: &RoomId) -> Result<Arc<HashSet<OwnedUserId>>>;
|
||||||
|
@ -106,4 +109,6 @@ pub trait Data: Send + Sync {
|
||||||
fn is_invited(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool>;
|
fn is_invited(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool>;
|
||||||
|
|
||||||
fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool>;
|
fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool>;
|
||||||
|
|
||||||
|
fn is_knocked(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,9 @@ impl Service {
|
||||||
MembershipState::Leave | MembershipState::Ban => {
|
MembershipState::Leave | MembershipState::Ban => {
|
||||||
self.db.mark_as_left(user_id, room_id)?;
|
self.db.mark_as_left(user_id, room_id)?;
|
||||||
}
|
}
|
||||||
|
MembershipState::Knock => {
|
||||||
|
self.db.mark_as_knocked(user_id, room_id)?;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,4 +353,9 @@ impl Service {
|
||||||
pub fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
|
pub fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
|
||||||
self.db.is_left(user_id, room_id)
|
self.db.is_left(user_id, room_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(self))]
|
||||||
|
pub fn is_knocked(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
|
||||||
|
self.db.is_knocked(user_id, room_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue