devirtualize service Data traits
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
a6edaad6fc
commit
7ad7badd60
64 changed files with 1190 additions and 1176 deletions
|
@ -1,31 +1,26 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{api::client::error::ErrorKind, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, UserId};
|
||||
|
||||
use crate::{services, utils, Error, KeyValueDatabase, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Creates or updates the alias to the given room id.
|
||||
fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId, user_id: &UserId) -> Result<()>;
|
||||
|
||||
/// Forgets about an alias. Returns an error if the alias did not exist.
|
||||
fn remove_alias(&self, alias: &RoomAliasId) -> Result<()>;
|
||||
|
||||
/// Looks up the roomid for the given alias.
|
||||
fn resolve_local_alias(&self, alias: &RoomAliasId) -> Result<Option<OwnedRoomId>>;
|
||||
|
||||
/// Finds the user who assigned the given alias to a room
|
||||
fn who_created_alias(&self, alias: &RoomAliasId) -> Result<Option<OwnedUserId>>;
|
||||
|
||||
/// Returns all local aliases that point to the given room
|
||||
fn local_aliases_for_room<'a>(
|
||||
&'a self, room_id: &RoomId,
|
||||
) -> Box<dyn Iterator<Item = Result<OwnedRoomAliasId>> + 'a>;
|
||||
|
||||
/// Returns all local aliases on the server
|
||||
fn all_local_aliases<'a>(&'a self) -> Box<dyn Iterator<Item = Result<(OwnedRoomId, String)>> + 'a>;
|
||||
pub struct Data {
|
||||
alias_userid: Arc<dyn KvTree>,
|
||||
alias_roomid: Arc<dyn KvTree>,
|
||||
aliasid_alias: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId, user_id: &UserId) -> Result<()> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
alias_userid: db.alias_userid.clone(),
|
||||
alias_roomid: db.alias_roomid.clone(),
|
||||
aliasid_alias: db.aliasid_alias.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId, user_id: &UserId) -> Result<()> {
|
||||
// Comes first as we don't want a stuck alias
|
||||
self.alias_userid
|
||||
.insert(alias.alias().as_bytes(), user_id.as_bytes())?;
|
||||
|
@ -41,7 +36,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_alias(&self, alias: &RoomAliasId) -> Result<()> {
|
||||
pub(super) fn remove_alias(&self, alias: &RoomAliasId) -> Result<()> {
|
||||
if let Some(room_id) = self.alias_roomid.get(alias.alias().as_bytes())? {
|
||||
let mut prefix = room_id;
|
||||
prefix.push(0xFF);
|
||||
|
@ -60,7 +55,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn resolve_local_alias(&self, alias: &RoomAliasId) -> Result<Option<OwnedRoomId>> {
|
||||
pub fn resolve_local_alias(&self, alias: &RoomAliasId) -> Result<Option<OwnedRoomId>> {
|
||||
self.alias_roomid
|
||||
.get(alias.alias().as_bytes())?
|
||||
.map(|bytes| {
|
||||
|
@ -73,7 +68,7 @@ impl Data for KeyValueDatabase {
|
|||
.transpose()
|
||||
}
|
||||
|
||||
fn who_created_alias(&self, alias: &RoomAliasId) -> Result<Option<OwnedUserId>> {
|
||||
pub(super) fn who_created_alias(&self, alias: &RoomAliasId) -> Result<Option<OwnedUserId>> {
|
||||
self.alias_userid
|
||||
.get(alias.alias().as_bytes())?
|
||||
.map(|bytes| {
|
||||
|
@ -86,7 +81,7 @@ impl Data for KeyValueDatabase {
|
|||
.transpose()
|
||||
}
|
||||
|
||||
fn local_aliases_for_room<'a>(
|
||||
pub fn local_aliases_for_room<'a>(
|
||||
&'a self, room_id: &RoomId,
|
||||
) -> Box<dyn Iterator<Item = Result<OwnedRoomAliasId>> + 'a> {
|
||||
let mut prefix = room_id.as_bytes().to_vec();
|
||||
|
@ -100,7 +95,7 @@ impl Data for KeyValueDatabase {
|
|||
}))
|
||||
}
|
||||
|
||||
fn all_local_aliases<'a>(&'a self) -> Box<dyn Iterator<Item = Result<(OwnedRoomId, String)>> + 'a> {
|
||||
pub fn all_local_aliases<'a>(&'a self) -> Box<dyn Iterator<Item = Result<(OwnedRoomId, String)>> + 'a> {
|
||||
Box::new(
|
||||
self.alias_roomid
|
||||
.iter()
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -15,10 +18,16 @@ use ruma::{
|
|||
use crate::{services, Error, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId, user_id: &UserId) -> Result<()> {
|
||||
if alias == services().globals.admin_alias && user_id != services().globals.server_user {
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
use std::{mem::size_of, sync::Arc};
|
||||
|
||||
use database::KvTree;
|
||||
|
||||
use crate::{utils, KeyValueDatabase, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn get_cached_eventid_authchain(&self, shorteventid: &[u64]) -> Result<Option<Arc<[u64]>>>;
|
||||
fn cache_auth_chain(&self, shorteventid: Vec<u64>, auth_chain: Arc<[u64]>) -> Result<()>;
|
||||
pub(super) struct Data {
|
||||
shorteventid_authchain: Arc<dyn KvTree>,
|
||||
db: Arc<KeyValueDatabase>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn get_cached_eventid_authchain(&self, key: &[u64]) -> Result<Option<Arc<[u64]>>> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
shorteventid_authchain: db.shorteventid_authchain.clone(),
|
||||
db: db.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_cached_eventid_authchain(&self, key: &[u64]) -> Result<Option<Arc<[u64]>>> {
|
||||
// Check RAM cache
|
||||
if let Some(result) = self.auth_chain_cache.lock().unwrap().get_mut(key) {
|
||||
if let Some(result) = self.db.auth_chain_cache.lock().unwrap().get_mut(key) {
|
||||
return Ok(Some(Arc::clone(result)));
|
||||
}
|
||||
|
||||
|
@ -29,7 +38,8 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
if let Some(chain) = chain {
|
||||
// Cache in RAM
|
||||
self.auth_chain_cache
|
||||
self.db
|
||||
.auth_chain_cache
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(vec![key[0]], Arc::clone(&chain));
|
||||
|
@ -41,7 +51,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
fn cache_auth_chain(&self, key: Vec<u64>, auth_chain: Arc<[u64]>) -> Result<()> {
|
||||
pub(super) fn cache_auth_chain(&self, key: Vec<u64>, auth_chain: Arc<[u64]>) -> Result<()> {
|
||||
// Only persist single events in db
|
||||
if key.len() == 1 {
|
||||
self.shorteventid_authchain.insert(
|
||||
|
@ -54,7 +64,8 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
// Cache in RAM
|
||||
self.auth_chain_cache
|
||||
self.db
|
||||
.auth_chain_cache
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(key, auth_chain);
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
use std::{
|
||||
collections::{BTreeSet, HashSet},
|
||||
|
@ -11,10 +14,16 @@ use tracing::{debug, error, trace, warn};
|
|||
use crate::{services, Error, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn event_ids_iter<'a>(
|
||||
&self, room_id: &RoomId, starting_events_: Vec<Arc<EventId>>,
|
||||
) -> Result<impl Iterator<Item = Arc<EventId>> + 'a> {
|
||||
|
|
|
@ -1,31 +1,34 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{OwnedRoomId, RoomId};
|
||||
|
||||
use crate::{utils, Error, KeyValueDatabase, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Adds the room to the public room directory
|
||||
fn set_public(&self, room_id: &RoomId) -> Result<()>;
|
||||
|
||||
/// Removes the room from the public room directory.
|
||||
fn set_not_public(&self, room_id: &RoomId) -> Result<()>;
|
||||
|
||||
/// Returns true if the room is in the public room directory.
|
||||
fn is_public_room(&self, room_id: &RoomId) -> Result<bool>;
|
||||
|
||||
/// Returns the unsorted public room directory
|
||||
fn public_rooms<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a>;
|
||||
pub(super) struct Data {
|
||||
publicroomids: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn set_public(&self, room_id: &RoomId) -> Result<()> { self.publicroomids.insert(room_id.as_bytes(), &[]) }
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
publicroomids: db.publicroomids.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_not_public(&self, room_id: &RoomId) -> Result<()> { self.publicroomids.remove(room_id.as_bytes()) }
|
||||
pub(super) fn set_public(&self, room_id: &RoomId) -> Result<()> {
|
||||
self.publicroomids.insert(room_id.as_bytes(), &[])
|
||||
}
|
||||
|
||||
fn is_public_room(&self, room_id: &RoomId) -> Result<bool> {
|
||||
pub(super) fn set_not_public(&self, room_id: &RoomId) -> Result<()> {
|
||||
self.publicroomids.remove(room_id.as_bytes())
|
||||
}
|
||||
|
||||
pub(super) fn is_public_room(&self, room_id: &RoomId) -> Result<bool> {
|
||||
Ok(self.publicroomids.get(room_id.as_bytes())?.is_some())
|
||||
}
|
||||
|
||||
fn public_rooms<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
|
||||
pub(super) fn public_rooms<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
|
||||
Box::new(self.publicroomids.iter().map(|(bytes, _)| {
|
||||
RoomId::parse(
|
||||
utils::string_from_bytes(&bytes)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -8,10 +11,16 @@ use ruma::{OwnedRoomId, RoomId};
|
|||
use crate::Result;
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn set_public(&self, room_id: &RoomId) -> Result<()> { self.db.set_public(room_id) }
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod parse_incoming_pdu;
|
||||
mod signing_keys;
|
||||
pub struct Service;
|
||||
|
||||
use std::{
|
||||
cmp,
|
||||
|
@ -32,6 +34,8 @@ use tracing::{debug, error, info, trace, warn};
|
|||
use super::state_compressor::CompressedStateEvent;
|
||||
use crate::{debug_error, debug_info, pdu, services, Error, PduEvent, Result};
|
||||
|
||||
pub struct Service;
|
||||
|
||||
// We use some AsyncRecursiveType hacks here so we can call async funtion
|
||||
// recursively.
|
||||
type AsyncRecursiveType<'a, T> = Pin<Box<dyn Future<Output = T> + 'a + Send>>;
|
||||
|
@ -41,6 +45,8 @@ type AsyncRecursiveCanonicalJsonResult<'a> =
|
|||
AsyncRecursiveType<'a, Result<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)>>;
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, _db: &Arc<KeyValueDatabase>) -> Result<Self> { Ok(Self {}) }
|
||||
|
||||
/// When receiving an event one needs to:
|
||||
/// 0. Check the server is in the room
|
||||
/// 1. Skip the PDU if we already know about it
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{DeviceId, RoomId, UserId};
|
||||
|
||||
use crate::{KeyValueDatabase, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn lazy_load_was_sent_before(
|
||||
&self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId, ll_user: &UserId,
|
||||
) -> Result<bool>;
|
||||
|
||||
fn lazy_load_confirm_delivery(
|
||||
&self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId,
|
||||
confirmed_user_ids: &mut dyn Iterator<Item = &UserId>,
|
||||
) -> Result<()>;
|
||||
|
||||
fn lazy_load_reset(&self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId) -> Result<()>;
|
||||
pub struct Data {
|
||||
lazyloadedids: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn lazy_load_was_sent_before(
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
lazyloadedids: db.lazyloadedids.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn lazy_load_was_sent_before(
|
||||
&self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId, ll_user: &UserId,
|
||||
) -> Result<bool> {
|
||||
let mut key = user_id.as_bytes().to_vec();
|
||||
|
@ -29,7 +29,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(self.lazyloadedids.get(&key)?.is_some())
|
||||
}
|
||||
|
||||
fn lazy_load_confirm_delivery(
|
||||
pub(super) fn lazy_load_confirm_delivery(
|
||||
&self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId,
|
||||
confirmed_user_ids: &mut dyn Iterator<Item = &UserId>,
|
||||
) -> Result<()> {
|
||||
|
@ -49,7 +49,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn lazy_load_reset(&self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId) -> Result<()> {
|
||||
pub(super) fn lazy_load_reset(&self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId) -> Result<()> {
|
||||
let mut prefix = user_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
prefix.extend_from_slice(device_id.as_bytes());
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
|
@ -11,13 +14,20 @@ use tokio::sync::Mutex;
|
|||
use crate::{PduCount, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub lazy_load_waiting: Mutex<HashMap<(OwnedUserId, OwnedDeviceId, OwnedRoomId, PduCount), HashSet<OwnedUserId>>>,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
lazy_load_waiting: Mutex::new(HashMap::new()),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn lazy_load_was_sent_before(
|
||||
&self, user_id: &UserId, device_id: &DeviceId, room_id: &RoomId, ll_user: &UserId,
|
||||
|
|
|
@ -1,20 +1,29 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{OwnedRoomId, RoomId};
|
||||
use tracing::error;
|
||||
|
||||
use crate::{services, utils, Error, KeyValueDatabase, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn exists(&self, room_id: &RoomId) -> Result<bool>;
|
||||
fn iter_ids<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a>;
|
||||
fn is_disabled(&self, room_id: &RoomId) -> Result<bool>;
|
||||
fn disable_room(&self, room_id: &RoomId, disabled: bool) -> Result<()>;
|
||||
fn is_banned(&self, room_id: &RoomId) -> Result<bool>;
|
||||
fn ban_room(&self, room_id: &RoomId, banned: bool) -> Result<()>;
|
||||
fn list_banned_rooms<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a>;
|
||||
pub struct Data {
|
||||
disabledroomids: Arc<dyn KvTree>,
|
||||
bannedroomids: Arc<dyn KvTree>,
|
||||
roomid_shortroomid: Arc<dyn KvTree>,
|
||||
pduid_pdu: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn exists(&self, room_id: &RoomId) -> Result<bool> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
disabledroomids: db.disabledroomids.clone(),
|
||||
bannedroomids: db.bannedroomids.clone(),
|
||||
roomid_shortroomid: db.roomid_shortroomid.clone(),
|
||||
pduid_pdu: db.pduid_pdu.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn exists(&self, room_id: &RoomId) -> Result<bool> {
|
||||
let prefix = match services().rooms.short.get_shortroomid(room_id)? {
|
||||
Some(b) => b.to_be_bytes().to_vec(),
|
||||
None => return Ok(false),
|
||||
|
@ -29,7 +38,7 @@ impl Data for KeyValueDatabase {
|
|||
.is_some())
|
||||
}
|
||||
|
||||
fn iter_ids<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
|
||||
pub(super) fn iter_ids<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
|
||||
Box::new(self.roomid_shortroomid.iter().map(|(bytes, _)| {
|
||||
RoomId::parse(
|
||||
utils::string_from_bytes(&bytes)
|
||||
|
@ -39,11 +48,11 @@ impl Data for KeyValueDatabase {
|
|||
}))
|
||||
}
|
||||
|
||||
fn is_disabled(&self, room_id: &RoomId) -> Result<bool> {
|
||||
pub(super) fn is_disabled(&self, room_id: &RoomId) -> Result<bool> {
|
||||
Ok(self.disabledroomids.get(room_id.as_bytes())?.is_some())
|
||||
}
|
||||
|
||||
fn disable_room(&self, room_id: &RoomId, disabled: bool) -> Result<()> {
|
||||
pub(super) fn disable_room(&self, room_id: &RoomId, disabled: bool) -> Result<()> {
|
||||
if disabled {
|
||||
self.disabledroomids.insert(room_id.as_bytes(), &[])?;
|
||||
} else {
|
||||
|
@ -53,9 +62,11 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn is_banned(&self, room_id: &RoomId) -> Result<bool> { Ok(self.bannedroomids.get(room_id.as_bytes())?.is_some()) }
|
||||
pub(super) fn is_banned(&self, room_id: &RoomId) -> Result<bool> {
|
||||
Ok(self.bannedroomids.get(room_id.as_bytes())?.is_some())
|
||||
}
|
||||
|
||||
fn ban_room(&self, room_id: &RoomId, banned: bool) -> Result<()> {
|
||||
pub(super) fn ban_room(&self, room_id: &RoomId, banned: bool) -> Result<()> {
|
||||
if banned {
|
||||
self.bannedroomids.insert(room_id.as_bytes(), &[])?;
|
||||
} else {
|
||||
|
@ -65,7 +76,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn list_banned_rooms<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
|
||||
pub(super) fn list_banned_rooms<'a>(&'a self) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
|
||||
Box::new(self.bannedroomids.iter().map(
|
||||
|(room_id_bytes, _ /* non-banned rooms should not be in this table */)| {
|
||||
let room_id = utils::string_from_bytes(&room_id_bytes)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -8,10 +11,16 @@ use ruma::{OwnedRoomId, RoomId};
|
|||
use crate::Result;
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
/// Checks if a room exists.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn exists(&self, room_id: &RoomId) -> Result<bool> { self.db.exists(room_id) }
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{CanonicalJsonObject, EventId};
|
||||
|
||||
use crate::{Error, KeyValueDatabase, PduEvent, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn get_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>>;
|
||||
fn get_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>>;
|
||||
fn add_pdu_outlier(&self, event_id: &EventId, pdu: &CanonicalJsonObject) -> Result<()>;
|
||||
pub struct Data {
|
||||
eventid_outlierpdu: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn get_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
eventid_outlierpdu: db.eventid_outlierpdu.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
|
||||
self.eventid_outlierpdu
|
||||
.get(event_id.as_bytes())?
|
||||
.map_or(Ok(None), |pdu| {
|
||||
|
@ -17,7 +24,7 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn get_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>> {
|
||||
pub(super) fn get_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>> {
|
||||
self.eventid_outlierpdu
|
||||
.get(event_id.as_bytes())?
|
||||
.map_or(Ok(None), |pdu| {
|
||||
|
@ -25,7 +32,7 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn add_pdu_outlier(&self, event_id: &EventId, pdu: &CanonicalJsonObject) -> Result<()> {
|
||||
pub(super) fn add_pdu_outlier(&self, event_id: &EventId, pdu: &CanonicalJsonObject) -> Result<()> {
|
||||
self.eventid_outlierpdu.insert(
|
||||
event_id.as_bytes(),
|
||||
&serde_json::to_vec(&pdu).expect("CanonicalJsonObject is valid"),
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -8,10 +11,16 @@ use ruma::{CanonicalJsonObject, EventId};
|
|||
use crate::{PduEvent, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the pdu from the outlier tree.
|
||||
pub fn get_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
|
||||
self.db.get_outlier_pdu_json(event_id)
|
||||
|
|
|
@ -1,30 +1,33 @@
|
|||
use std::{mem::size_of, sync::Arc};
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{EventId, RoomId, UserId};
|
||||
|
||||
use crate::{services, utils, Error, KeyValueDatabase, PduCount, PduEvent, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn add_relation(&self, from: u64, to: u64) -> Result<()>;
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn relations_until<'a>(
|
||||
&'a self, user_id: &'a UserId, room_id: u64, target: u64, until: PduCount,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<(PduCount, PduEvent)>> + 'a>>;
|
||||
fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[Arc<EventId>]) -> Result<()>;
|
||||
fn is_event_referenced(&self, room_id: &RoomId, event_id: &EventId) -> Result<bool>;
|
||||
fn mark_event_soft_failed(&self, event_id: &EventId) -> Result<()>;
|
||||
fn is_event_soft_failed(&self, event_id: &EventId) -> Result<bool>;
|
||||
pub(super) struct Data {
|
||||
tofrom_relation: Arc<dyn KvTree>,
|
||||
referencedevents: Arc<dyn KvTree>,
|
||||
softfailedeventids: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn add_relation(&self, from: u64, to: u64) -> Result<()> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
tofrom_relation: db.tofrom_relation.clone(),
|
||||
referencedevents: db.referencedevents.clone(),
|
||||
softfailedeventids: db.softfailedeventids.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn add_relation(&self, from: u64, to: u64) -> Result<()> {
|
||||
let mut key = to.to_be_bytes().to_vec();
|
||||
key.extend_from_slice(&from.to_be_bytes());
|
||||
self.tofrom_relation.insert(&key, &[])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn relations_until<'a>(
|
||||
pub(super) fn relations_until<'a>(
|
||||
&'a self, user_id: &'a UserId, shortroomid: u64, target: u64, until: PduCount,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<(PduCount, PduEvent)>> + 'a>> {
|
||||
let prefix = target.to_be_bytes().to_vec();
|
||||
|
@ -63,7 +66,7 @@ impl Data for KeyValueDatabase {
|
|||
))
|
||||
}
|
||||
|
||||
fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[Arc<EventId>]) -> Result<()> {
|
||||
pub(super) fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[Arc<EventId>]) -> Result<()> {
|
||||
for prev in event_ids {
|
||||
let mut key = room_id.as_bytes().to_vec();
|
||||
key.extend_from_slice(prev.as_bytes());
|
||||
|
@ -73,17 +76,17 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn is_event_referenced(&self, room_id: &RoomId, event_id: &EventId) -> Result<bool> {
|
||||
pub(super) fn is_event_referenced(&self, room_id: &RoomId, event_id: &EventId) -> Result<bool> {
|
||||
let mut key = room_id.as_bytes().to_vec();
|
||||
key.extend_from_slice(event_id.as_bytes());
|
||||
Ok(self.referencedevents.get(&key)?.is_some())
|
||||
}
|
||||
|
||||
fn mark_event_soft_failed(&self, event_id: &EventId) -> Result<()> {
|
||||
pub(super) fn mark_event_soft_failed(&self, event_id: &EventId) -> Result<()> {
|
||||
self.softfailedeventids.insert(event_id.as_bytes(), &[])
|
||||
}
|
||||
|
||||
fn is_event_soft_failed(&self, event_id: &EventId) -> Result<bool> {
|
||||
pub(super) fn is_event_soft_failed(&self, event_id: &EventId) -> Result<bool> {
|
||||
self.softfailedeventids
|
||||
.get(event_id.as_bytes())
|
||||
.map(|o| o.is_some())
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -13,7 +16,7 @@ use serde::Deserialize;
|
|||
use crate::{services, PduCount, PduEvent, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
db: Data,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
|
@ -27,6 +30,12 @@ struct ExtractRelatesToEventId {
|
|||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, from, to))]
|
||||
pub fn add_relation(&self, from: PduCount, to: PduCount) -> Result<()> {
|
||||
match (from, to) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::mem::size_of;
|
||||
use std::{mem::size_of, sync::Arc};
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{
|
||||
events::{receipt::ReceiptEvent, AnySyncEphemeralRoomEvent},
|
||||
serde::Raw,
|
||||
|
@ -11,32 +12,22 @@ use crate::{services, utils, Error, KeyValueDatabase, Result};
|
|||
type AnySyncEphemeralRoomEventIter<'a> =
|
||||
Box<dyn Iterator<Item = Result<(OwnedUserId, u64, Raw<AnySyncEphemeralRoomEvent>)>> + 'a>;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Replaces the previous read receipt.
|
||||
fn readreceipt_update(&self, user_id: &UserId, room_id: &RoomId, event: ReceiptEvent) -> Result<()>;
|
||||
|
||||
/// Returns an iterator over the most recent read_receipts in a room that
|
||||
/// happened after the event with id `since`.
|
||||
fn readreceipts_since(&self, room_id: &RoomId, since: u64) -> AnySyncEphemeralRoomEventIter<'_>;
|
||||
|
||||
/// Sets a private read marker at `count`.
|
||||
fn private_read_set(&self, room_id: &RoomId, user_id: &UserId, count: u64) -> Result<()>;
|
||||
|
||||
/// Returns the private read marker.
|
||||
///
|
||||
/// TODO: use this?
|
||||
#[allow(dead_code)]
|
||||
fn private_read_get(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>>;
|
||||
|
||||
/// Returns the count of the last typing update in this room.
|
||||
///
|
||||
/// TODO: use this?
|
||||
#[allow(dead_code)]
|
||||
fn last_privateread_update(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64>;
|
||||
pub(super) struct Data {
|
||||
roomuserid_privateread: Arc<dyn KvTree>,
|
||||
roomuserid_lastprivatereadupdate: Arc<dyn KvTree>,
|
||||
readreceiptid_readreceipt: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn readreceipt_update(&self, user_id: &UserId, room_id: &RoomId, event: ReceiptEvent) -> Result<()> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
roomuserid_privateread: db.roomuserid_privateread.clone(),
|
||||
roomuserid_lastprivatereadupdate: db.roomuserid_lastprivatereadupdate.clone(),
|
||||
readreceiptid_readreceipt: db.readreceiptid_readreceipt.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn readreceipt_update(&self, user_id: &UserId, room_id: &RoomId, event: ReceiptEvent) -> Result<()> {
|
||||
let mut prefix = room_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -71,9 +62,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn readreceipts_since<'a>(
|
||||
&'a self, room_id: &RoomId, since: u64,
|
||||
) -> Box<dyn Iterator<Item = Result<(OwnedUserId, u64, Raw<AnySyncEphemeralRoomEvent>)>> + 'a> {
|
||||
pub(super) fn readreceipts_since<'a>(&'a self, room_id: &RoomId, since: u64) -> AnySyncEphemeralRoomEventIter<'a> {
|
||||
let mut prefix = room_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
let prefix2 = prefix.clone();
|
||||
|
@ -107,7 +96,7 @@ impl Data for KeyValueDatabase {
|
|||
)
|
||||
}
|
||||
|
||||
fn private_read_set(&self, room_id: &RoomId, user_id: &UserId, count: u64) -> Result<()> {
|
||||
pub(super) fn private_read_set(&self, room_id: &RoomId, user_id: &UserId, count: u64) -> Result<()> {
|
||||
let mut key = room_id.as_bytes().to_vec();
|
||||
key.push(0xFF);
|
||||
key.extend_from_slice(user_id.as_bytes());
|
||||
|
@ -119,7 +108,7 @@ impl Data for KeyValueDatabase {
|
|||
.insert(&key, &services().globals.next_count()?.to_be_bytes())
|
||||
}
|
||||
|
||||
fn private_read_get(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
|
||||
pub(super) fn private_read_get(&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());
|
||||
|
@ -133,7 +122,7 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn last_privateread_update(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||
pub(super) fn last_privateread_update(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||
let mut key = room_id.as_bytes().to_vec();
|
||||
key.push(0xFF);
|
||||
key.extend_from_slice(user_id.as_bytes());
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -8,10 +11,16 @@ use ruma::{events::receipt::ReceiptEvent, serde::Raw, OwnedUserId, RoomId, UserI
|
|||
use crate::{services, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
/// Replaces the previous read receipt.
|
||||
pub fn readreceipt_update(&self, user_id: &UserId, room_id: &RoomId, event: ReceiptEvent) -> Result<()> {
|
||||
self.db.readreceipt_update(user_id, room_id, event)?;
|
||||
|
|
|
@ -1,30 +1,24 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::RoomId;
|
||||
|
||||
use crate::{services, utils, KeyValueDatabase, Result};
|
||||
|
||||
type SearchPdusResult<'a> = Result<Option<(Box<dyn Iterator<Item = Vec<u8>> + 'a>, Vec<String>)>>;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn index_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()>;
|
||||
|
||||
fn deindex_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()>;
|
||||
|
||||
fn search_pdus<'a>(&'a self, room_id: &RoomId, search_string: &str) -> SearchPdusResult<'a>;
|
||||
pub struct Data {
|
||||
tokenids: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
/// Splits a string into tokens used as keys in the search inverted index
|
||||
///
|
||||
/// This may be used to tokenize both message bodies (for indexing) or search
|
||||
/// queries (for querying).
|
||||
fn tokenize(body: &str) -> impl Iterator<Item = String> + '_ {
|
||||
body.split_terminator(|c: char| !c.is_alphanumeric())
|
||||
.filter(|s| !s.is_empty())
|
||||
.filter(|word| word.len() <= 50)
|
||||
.map(str::to_lowercase)
|
||||
}
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
tokenids: db.tokenids.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn index_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
||||
pub(super) fn index_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
||||
let mut batch = tokenize(message_body).map(|word| {
|
||||
let mut key = shortroomid.to_be_bytes().to_vec();
|
||||
key.extend_from_slice(word.as_bytes());
|
||||
|
@ -36,7 +30,7 @@ impl Data for KeyValueDatabase {
|
|||
self.tokenids.insert_batch(&mut batch)
|
||||
}
|
||||
|
||||
fn deindex_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
||||
pub(super) fn deindex_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
||||
let batch = tokenize(message_body).map(|word| {
|
||||
let mut key = shortroomid.to_be_bytes().to_vec();
|
||||
key.extend_from_slice(word.as_bytes());
|
||||
|
@ -52,7 +46,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn search_pdus<'a>(&'a self, room_id: &RoomId, search_string: &str) -> SearchPdusResult<'a> {
|
||||
pub(super) fn search_pdus<'a>(&'a self, room_id: &RoomId, search_string: &str) -> SearchPdusResult<'a> {
|
||||
let prefix = services()
|
||||
.rooms
|
||||
.short
|
||||
|
@ -88,3 +82,14 @@ impl Data for KeyValueDatabase {
|
|||
Ok(Some((Box::new(common_elements), words)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Splits a string into tokens used as keys in the search inverted index
|
||||
///
|
||||
/// This may be used to tokenize both message bodies (for indexing) or search
|
||||
/// queries (for querying).
|
||||
fn tokenize(body: &str) -> impl Iterator<Item = String> + '_ {
|
||||
body.split_terminator(|c: char| !c.is_alphanumeric())
|
||||
.filter(|s| !s.is_empty())
|
||||
.filter(|word| word.len() <= 50)
|
||||
.map(str::to_lowercase)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -8,10 +11,16 @@ use ruma::RoomId;
|
|||
use crate::Result;
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn index_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
||||
self.db.index_pdu(shortroomid, pdu_id, message_body)
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use conduit::warn;
|
||||
use database::{KeyValueDatabase, KvTree};
|
||||
use ruma::{events::StateEventType, EventId, RoomId};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{services, utils, Error, KeyValueDatabase, Result};
|
||||
use crate::{services, utils, Error, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn get_or_create_shorteventid(&self, event_id: &EventId) -> Result<u64>;
|
||||
|
||||
fn multi_get_or_create_shorteventid(&self, event_id: &[&EventId]) -> Result<Vec<u64>>;
|
||||
|
||||
fn get_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<Option<u64>>;
|
||||
|
||||
fn get_or_create_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<u64>;
|
||||
|
||||
fn get_eventid_from_short(&self, shorteventid: u64) -> Result<Arc<EventId>>;
|
||||
|
||||
fn get_statekey_from_short(&self, shortstatekey: u64) -> Result<(StateEventType, String)>;
|
||||
|
||||
/// Returns (shortstatehash, already_existed)
|
||||
fn get_or_create_shortstatehash(&self, state_hash: &[u8]) -> Result<(u64, bool)>;
|
||||
|
||||
fn get_shortroomid(&self, room_id: &RoomId) -> Result<Option<u64>>;
|
||||
|
||||
fn get_or_create_shortroomid(&self, room_id: &RoomId) -> Result<u64>;
|
||||
pub(super) struct Data {
|
||||
eventid_shorteventid: Arc<dyn KvTree>,
|
||||
shorteventid_eventid: Arc<dyn KvTree>,
|
||||
statekey_shortstatekey: Arc<dyn KvTree>,
|
||||
shortstatekey_statekey: Arc<dyn KvTree>,
|
||||
roomid_shortroomid: Arc<dyn KvTree>,
|
||||
statehash_shortstatehash: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn get_or_create_shorteventid(&self, event_id: &EventId) -> Result<u64> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
eventid_shorteventid: db.eventid_shorteventid.clone(),
|
||||
shorteventid_eventid: db.shorteventid_eventid.clone(),
|
||||
statekey_shortstatekey: db.statekey_shortstatekey.clone(),
|
||||
shortstatekey_statekey: db.shortstatekey_statekey.clone(),
|
||||
roomid_shortroomid: db.roomid_shortroomid.clone(),
|
||||
statehash_shortstatehash: db.statehash_shortstatehash.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_or_create_shorteventid(&self, event_id: &EventId) -> Result<u64> {
|
||||
let short = if let Some(shorteventid) = self.eventid_shorteventid.get(event_id.as_bytes())? {
|
||||
utils::u64_from_bytes(&shorteventid).map_err(|_| Error::bad_database("Invalid shorteventid in db."))?
|
||||
} else {
|
||||
|
@ -42,7 +42,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(short)
|
||||
}
|
||||
|
||||
fn multi_get_or_create_shorteventid(&self, event_ids: &[&EventId]) -> Result<Vec<u64>> {
|
||||
pub(super) fn multi_get_or_create_shorteventid(&self, event_ids: &[&EventId]) -> Result<Vec<u64>> {
|
||||
let mut ret: Vec<u64> = Vec::with_capacity(event_ids.len());
|
||||
let keys = event_ids
|
||||
.iter()
|
||||
|
@ -74,7 +74,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(ret)
|
||||
}
|
||||
|
||||
fn get_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<Option<u64>> {
|
||||
pub(super) fn get_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<Option<u64>> {
|
||||
let mut statekey_vec = event_type.to_string().as_bytes().to_vec();
|
||||
statekey_vec.push(0xFF);
|
||||
statekey_vec.extend_from_slice(state_key.as_bytes());
|
||||
|
@ -90,7 +90,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(short)
|
||||
}
|
||||
|
||||
fn get_or_create_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<u64> {
|
||||
pub(super) fn get_or_create_shortstatekey(&self, event_type: &StateEventType, state_key: &str) -> Result<u64> {
|
||||
let mut statekey_vec = event_type.to_string().as_bytes().to_vec();
|
||||
statekey_vec.push(0xFF);
|
||||
statekey_vec.extend_from_slice(state_key.as_bytes());
|
||||
|
@ -109,7 +109,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(short)
|
||||
}
|
||||
|
||||
fn get_eventid_from_short(&self, shorteventid: u64) -> Result<Arc<EventId>> {
|
||||
pub(super) fn get_eventid_from_short(&self, shorteventid: u64) -> Result<Arc<EventId>> {
|
||||
let bytes = self
|
||||
.shorteventid_eventid
|
||||
.get(&shorteventid.to_be_bytes())?
|
||||
|
@ -124,7 +124,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(event_id)
|
||||
}
|
||||
|
||||
fn get_statekey_from_short(&self, shortstatekey: u64) -> Result<(StateEventType, String)> {
|
||||
pub(super) fn get_statekey_from_short(&self, shortstatekey: u64) -> Result<(StateEventType, String)> {
|
||||
let bytes = self
|
||||
.shortstatekey_statekey
|
||||
.get(&shortstatekey.to_be_bytes())?
|
||||
|
@ -150,7 +150,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Returns (shortstatehash, already_existed)
|
||||
fn get_or_create_shortstatehash(&self, state_hash: &[u8]) -> Result<(u64, bool)> {
|
||||
pub(super) fn get_or_create_shortstatehash(&self, state_hash: &[u8]) -> Result<(u64, bool)> {
|
||||
Ok(if let Some(shortstatehash) = self.statehash_shortstatehash.get(state_hash)? {
|
||||
(
|
||||
utils::u64_from_bytes(&shortstatehash)
|
||||
|
@ -165,14 +165,14 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn get_shortroomid(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||
pub(super) fn get_shortroomid(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||
self.roomid_shortroomid
|
||||
.get(room_id.as_bytes())?
|
||||
.map(|bytes| utils::u64_from_bytes(&bytes).map_err(|_| Error::bad_database("Invalid shortroomid in db.")))
|
||||
.transpose()
|
||||
}
|
||||
|
||||
fn get_or_create_shortroomid(&self, room_id: &RoomId) -> Result<u64> {
|
||||
pub(super) fn get_or_create_shortroomid(&self, room_id: &RoomId) -> Result<u64> {
|
||||
Ok(if let Some(short) = self.roomid_shortroomid.get(room_id.as_bytes())? {
|
||||
utils::u64_from_bytes(&short).map_err(|_| Error::bad_database("Invalid shortroomid in db."))?
|
||||
} else {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -7,10 +10,16 @@ use ruma::{events::StateEventType, EventId, RoomId};
|
|||
use crate::Result;
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_or_create_shorteventid(&self, event_id: &EventId) -> Result<u64> {
|
||||
self.db.get_or_create_shorteventid(event_id)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use std::{
|
||||
fmt::{Display, Formatter},
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
use lru_cache::LruCache;
|
||||
use ruma::{
|
||||
api::{
|
||||
|
@ -330,6 +333,16 @@ impl From<CachedSpaceHierarchySummary> for SpaceHierarchyRoomsChunk {
|
|||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(server: &Arc<Server>, _db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
let config = &server.config;
|
||||
Ok(Self {
|
||||
roomid_spacehierarchy_cache: Mutex::new(LruCache::new(
|
||||
(f64::from(config.roomid_spacehierarchy_cache_capacity) * config.conduit_cache_capacity_modifier)
|
||||
as usize,
|
||||
)),
|
||||
})
|
||||
}
|
||||
|
||||
///Gets the response for the space hierarchy over federation request
|
||||
///
|
||||
///Panics if the room does not exist, so a check if the room exists should
|
||||
|
|
|
@ -1,39 +1,27 @@
|
|||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use conduit::utils::mutex_map;
|
||||
use database::KvTree;
|
||||
use ruma::{EventId, OwnedEventId, RoomId};
|
||||
|
||||
use crate::{utils, Error, KeyValueDatabase, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Returns the last state hash key added to the db for the given room.
|
||||
fn get_room_shortstatehash(&self, room_id: &RoomId) -> Result<Option<u64>>;
|
||||
|
||||
/// Set the state hash to a new version, but does not update `state_cache`.
|
||||
fn set_room_state(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
new_shortstatehash: u64,
|
||||
_mutex_lock: &mutex_map::Guard<()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<()>;
|
||||
|
||||
/// Associates a state with an event.
|
||||
fn set_event_state(&self, shorteventid: u64, shortstatehash: u64) -> Result<()>;
|
||||
|
||||
/// Returns all events we would send as the `prev_events` of the next event.
|
||||
fn get_forward_extremities(&self, room_id: &RoomId) -> Result<HashSet<Arc<EventId>>>;
|
||||
|
||||
/// Replace the forward extremities of the room.
|
||||
fn set_forward_extremities(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
event_ids: Vec<OwnedEventId>,
|
||||
_mutex_lock: &mutex_map::Guard<()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<()>;
|
||||
pub struct Data {
|
||||
shorteventid_shortstatehash: Arc<dyn KvTree>,
|
||||
roomid_pduleaves: Arc<dyn KvTree>,
|
||||
roomid_shortstatehash: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn get_room_shortstatehash(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
shorteventid_shortstatehash: db.shorteventid_shortstatehash.clone(),
|
||||
roomid_pduleaves: db.roomid_pduleaves.clone(),
|
||||
roomid_shortstatehash: db.roomid_shortstatehash.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_room_shortstatehash(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||
self.roomid_shortstatehash
|
||||
.get(room_id.as_bytes())?
|
||||
.map_or(Ok(None), |bytes| {
|
||||
|
@ -43,7 +31,7 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn set_room_state(
|
||||
pub(super) fn set_room_state(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
new_shortstatehash: u64,
|
||||
|
@ -54,13 +42,13 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn set_event_state(&self, shorteventid: u64, shortstatehash: u64) -> Result<()> {
|
||||
pub(super) fn set_event_state(&self, shorteventid: u64, shortstatehash: u64) -> Result<()> {
|
||||
self.shorteventid_shortstatehash
|
||||
.insert(&shorteventid.to_be_bytes(), &shortstatehash.to_be_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_forward_extremities(&self, room_id: &RoomId) -> Result<HashSet<Arc<EventId>>> {
|
||||
pub(super) fn get_forward_extremities(&self, room_id: &RoomId) -> Result<HashSet<Arc<EventId>>> {
|
||||
let mut prefix = room_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -76,7 +64,7 @@ impl Data for KeyValueDatabase {
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn set_forward_extremities(
|
||||
pub(super) fn set_forward_extremities(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
event_ids: Vec<OwnedEventId>,
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
|
@ -22,10 +25,16 @@ use super::state_compressor::CompressedStateEvent;
|
|||
use crate::{services, utils::calculate_hash, Error, PduEvent, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
/// Set the room to the given statehash and update caches.
|
||||
pub async fn force_state(
|
||||
&self,
|
||||
|
|
|
@ -1,56 +1,25 @@
|
|||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use database::KvTree;
|
||||
use ruma::{events::StateEventType, EventId, RoomId};
|
||||
|
||||
use crate::{services, utils, Error, KeyValueDatabase, PduEvent, Result};
|
||||
|
||||
#[async_trait]
|
||||
pub trait Data: Send + Sync {
|
||||
/// Builds a StateMap by iterating over all keys that start
|
||||
/// with state_hash, this gives the full state for the given state_hash.
|
||||
#[allow(unused_qualifications)] // async traits
|
||||
async fn state_full_ids(&self, shortstatehash: u64) -> Result<HashMap<u64, Arc<EventId>>>;
|
||||
|
||||
#[allow(unused_qualifications)] // async traits
|
||||
async fn state_full(&self, shortstatehash: u64) -> Result<HashMap<(StateEventType, String), Arc<PduEvent>>>;
|
||||
|
||||
/// Returns a single PDU from `room_id` with key (`event_type`,
|
||||
/// `state_key`).
|
||||
fn state_get_id(
|
||||
&self, shortstatehash: u64, event_type: &StateEventType, state_key: &str,
|
||||
) -> Result<Option<Arc<EventId>>>;
|
||||
|
||||
/// Returns a single PDU from `room_id` with key (`event_type`,
|
||||
/// `state_key`).
|
||||
fn state_get(
|
||||
&self, shortstatehash: u64, event_type: &StateEventType, state_key: &str,
|
||||
) -> Result<Option<Arc<PduEvent>>>;
|
||||
|
||||
/// Returns the state hash for this pdu.
|
||||
fn pdu_shortstatehash(&self, event_id: &EventId) -> Result<Option<u64>>;
|
||||
|
||||
/// Returns the full room state.
|
||||
#[allow(unused_qualifications)] // async traits
|
||||
async fn room_state_full(&self, room_id: &RoomId) -> Result<HashMap<(StateEventType, String), Arc<PduEvent>>>;
|
||||
|
||||
/// Returns a single PDU from `room_id` with key (`event_type`,
|
||||
/// `state_key`).
|
||||
fn room_state_get_id(
|
||||
&self, room_id: &RoomId, event_type: &StateEventType, state_key: &str,
|
||||
) -> Result<Option<Arc<EventId>>>;
|
||||
|
||||
/// Returns a single PDU from `room_id` with key (`event_type`,
|
||||
/// `state_key`).
|
||||
fn room_state_get(
|
||||
&self, room_id: &RoomId, event_type: &StateEventType, state_key: &str,
|
||||
) -> Result<Option<Arc<PduEvent>>>;
|
||||
pub struct Data {
|
||||
eventid_shorteventid: Arc<dyn KvTree>,
|
||||
shorteventid_shortstatehash: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Data for KeyValueDatabase {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
eventid_shorteventid: db.eventid_shorteventid.clone(),
|
||||
shorteventid_shortstatehash: db.shorteventid_shortstatehash.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_qualifications)] // async traits
|
||||
async fn state_full_ids(&self, shortstatehash: u64) -> Result<HashMap<u64, Arc<EventId>>> {
|
||||
pub(super) async fn state_full_ids(&self, shortstatehash: u64) -> Result<HashMap<u64, Arc<EventId>>> {
|
||||
let full_state = services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
|
@ -76,7 +45,9 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[allow(unused_qualifications)] // async traits
|
||||
async fn state_full(&self, shortstatehash: u64) -> Result<HashMap<(StateEventType, String), Arc<PduEvent>>> {
|
||||
pub(super) async fn state_full(
|
||||
&self, shortstatehash: u64,
|
||||
) -> Result<HashMap<(StateEventType, String), Arc<PduEvent>>> {
|
||||
let full_state = services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
|
@ -116,7 +87,8 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns a single PDU from `room_id` with key (`event_type`,
|
||||
/// `state_key`).
|
||||
fn state_get_id(
|
||||
#[allow(clippy::unused_self)]
|
||||
pub(super) fn state_get_id(
|
||||
&self, shortstatehash: u64, event_type: &StateEventType, state_key: &str,
|
||||
) -> Result<Option<Arc<EventId>>> {
|
||||
let Some(shortstatekey) = services()
|
||||
|
@ -148,7 +120,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns a single PDU from `room_id` with key (`event_type`,
|
||||
/// `state_key`).
|
||||
fn state_get(
|
||||
pub(super) fn state_get(
|
||||
&self, shortstatehash: u64, event_type: &StateEventType, state_key: &str,
|
||||
) -> Result<Option<Arc<PduEvent>>> {
|
||||
self.state_get_id(shortstatehash, event_type, state_key)?
|
||||
|
@ -156,7 +128,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Returns the state hash for this pdu.
|
||||
fn pdu_shortstatehash(&self, event_id: &EventId) -> Result<Option<u64>> {
|
||||
pub(super) fn pdu_shortstatehash(&self, event_id: &EventId) -> Result<Option<u64>> {
|
||||
self.eventid_shorteventid
|
||||
.get(event_id.as_bytes())?
|
||||
.map_or(Ok(None), |shorteventid| {
|
||||
|
@ -173,7 +145,9 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns the full room state.
|
||||
#[allow(unused_qualifications)] // async traits
|
||||
async fn room_state_full(&self, room_id: &RoomId) -> Result<HashMap<(StateEventType, String), Arc<PduEvent>>> {
|
||||
pub(super) async fn room_state_full(
|
||||
&self, room_id: &RoomId,
|
||||
) -> Result<HashMap<(StateEventType, String), Arc<PduEvent>>> {
|
||||
if let Some(current_shortstatehash) = services().rooms.state.get_room_shortstatehash(room_id)? {
|
||||
self.state_full(current_shortstatehash).await
|
||||
} else {
|
||||
|
@ -183,7 +157,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns a single PDU from `room_id` with key (`event_type`,
|
||||
/// `state_key`).
|
||||
fn room_state_get_id(
|
||||
pub(super) fn room_state_get_id(
|
||||
&self, room_id: &RoomId, event_type: &StateEventType, state_key: &str,
|
||||
) -> Result<Option<Arc<EventId>>> {
|
||||
if let Some(current_shortstatehash) = services().rooms.state.get_room_shortstatehash(room_id)? {
|
||||
|
@ -195,7 +169,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns a single PDU from `room_id` with key (`event_type`,
|
||||
/// `state_key`).
|
||||
fn room_state_get(
|
||||
pub(super) fn room_state_get(
|
||||
&self, room_id: &RoomId, event_type: &StateEventType, state_key: &str,
|
||||
) -> Result<Option<Arc<PduEvent>>> {
|
||||
if let Some(current_shortstatehash) = services().rooms.state.get_room_shortstatehash(room_id)? {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
use std::sync::Mutex as StdMutex;
|
||||
|
||||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
|
@ -29,12 +34,25 @@ use tracing::{error, warn};
|
|||
use crate::{service::pdu::PduBuilder, services, Error, PduEvent, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
pub server_visibility_cache: Mutex<LruCache<(OwnedServerName, u64), bool>>,
|
||||
pub user_visibility_cache: Mutex<LruCache<(OwnedUserId, u64), bool>>,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
let config = &server.config;
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
server_visibility_cache: StdMutex::new(LruCache::new(
|
||||
(f64::from(config.server_visibility_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
||||
)),
|
||||
user_visibility_cache: StdMutex::new(LruCache::new(
|
||||
(f64::from(config.user_visibility_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
||||
)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Builds a StateMap by iterating over all keys that start
|
||||
/// with state_hash, this gives the full state for the given state_hash.
|
||||
#[tracing::instrument(skip(self))]
|
||||
|
|
|
@ -17,101 +17,53 @@ use crate::{
|
|||
type StrippedStateEventIter<'a> = Box<dyn Iterator<Item = Result<(OwnedRoomId, Vec<Raw<AnyStrippedStateEvent>>)>> + 'a>;
|
||||
type AnySyncStateEventIter<'a> = Box<dyn Iterator<Item = Result<(OwnedRoomId, Vec<Raw<AnySyncStateEvent>>)>> + 'a>;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn mark_as_once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
fn mark_as_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
fn mark_as_invited(
|
||||
&self, user_id: &UserId, room_id: &RoomId, last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
|
||||
invite_via: Option<Vec<OwnedServerName>>,
|
||||
) -> Result<()>;
|
||||
fn mark_as_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn update_joined_count(&self, room_id: &RoomId) -> Result<()>;
|
||||
use database::KvTree;
|
||||
|
||||
fn appservice_in_room(&self, room_id: &RoomId, appservice: &RegistrationInfo) -> Result<bool>;
|
||||
|
||||
/// Makes a user forget a room.
|
||||
fn forget(&self, room_id: &RoomId, user_id: &UserId) -> Result<()>;
|
||||
|
||||
/// Returns an iterator of all servers participating in this room.
|
||||
fn room_servers<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedServerName>> + 'a>;
|
||||
|
||||
fn server_in_room(&self, server: &ServerName, room_id: &RoomId) -> Result<bool>;
|
||||
|
||||
/// Returns an iterator of all rooms a server participates in (as far as we
|
||||
/// know).
|
||||
fn server_rooms<'a>(&'a self, server: &ServerName) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a>;
|
||||
|
||||
/// Returns an iterator of all joined members of a room.
|
||||
fn room_members<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a>;
|
||||
|
||||
/// Returns an iterator of all our local users
|
||||
/// in the room, even if they're deactivated/guests
|
||||
fn local_users_in_room<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = OwnedUserId> + 'a>;
|
||||
|
||||
/// Returns an iterator of all our local joined users in a room who are
|
||||
/// active (not deactivated, not guest)
|
||||
fn active_local_users_in_room<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = OwnedUserId> + 'a>;
|
||||
|
||||
fn room_joined_count(&self, room_id: &RoomId) -> Result<Option<u64>>;
|
||||
|
||||
fn room_invited_count(&self, room_id: &RoomId) -> Result<Option<u64>>;
|
||||
|
||||
/// Returns an iterator over all User IDs who ever joined a room.
|
||||
///
|
||||
/// TODO: use this?
|
||||
#[allow(dead_code)]
|
||||
fn room_useroncejoined<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a>;
|
||||
|
||||
/// Returns an iterator over all invited members of a room.
|
||||
fn room_members_invited<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a>;
|
||||
|
||||
fn get_invite_count(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>>;
|
||||
|
||||
fn get_left_count(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>>;
|
||||
|
||||
/// Returns an iterator over all rooms this user joined.
|
||||
fn rooms_joined(&self, user_id: &UserId) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + '_>;
|
||||
|
||||
/// Returns an iterator over all rooms a user was invited to.
|
||||
fn rooms_invited<'a>(&'a self, user_id: &UserId) -> StrippedStateEventIter<'a>;
|
||||
|
||||
fn invite_state(&self, user_id: &UserId, room_id: &RoomId) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>>;
|
||||
|
||||
fn left_state(&self, user_id: &UserId, room_id: &RoomId) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>>;
|
||||
|
||||
/// Returns an iterator over all rooms a user left.
|
||||
fn rooms_left<'a>(&'a self, user_id: &UserId) -> AnySyncStateEventIter<'a>;
|
||||
|
||||
fn once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool>;
|
||||
|
||||
fn is_joined(&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>;
|
||||
|
||||
/// Gets the servers to either accept or decline invites via for a given
|
||||
/// room.
|
||||
fn servers_invite_via<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedServerName>> + 'a>;
|
||||
|
||||
/// Add the given servers the list to accept or decline invites via for a
|
||||
/// given room.
|
||||
///
|
||||
/// TODO: use this?
|
||||
#[allow(dead_code)]
|
||||
fn add_servers_invite_via(&self, room_id: &RoomId, servers: &[OwnedServerName]) -> Result<()>;
|
||||
pub struct Data {
|
||||
userroomid_joined: Arc<dyn KvTree>,
|
||||
roomuserid_joined: Arc<dyn KvTree>,
|
||||
userroomid_invitestate: Arc<dyn KvTree>,
|
||||
roomuserid_invitecount: Arc<dyn KvTree>,
|
||||
userroomid_leftstate: Arc<dyn KvTree>,
|
||||
roomuserid_leftcount: Arc<dyn KvTree>,
|
||||
roomid_inviteviaservers: Arc<dyn KvTree>,
|
||||
roomuseroncejoinedids: Arc<dyn KvTree>,
|
||||
roomid_joinedcount: Arc<dyn KvTree>,
|
||||
roomid_invitedcount: Arc<dyn KvTree>,
|
||||
roomserverids: Arc<dyn KvTree>,
|
||||
serverroomids: Arc<dyn KvTree>,
|
||||
db: Arc<KeyValueDatabase>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn mark_as_once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
userroomid_joined: db.userroomid_joined.clone(),
|
||||
roomuserid_joined: db.roomuserid_joined.clone(),
|
||||
userroomid_invitestate: db.userroomid_invitestate.clone(),
|
||||
roomuserid_invitecount: db.roomuserid_invitecount.clone(),
|
||||
userroomid_leftstate: db.userroomid_leftstate.clone(),
|
||||
roomuserid_leftcount: db.roomuserid_leftcount.clone(),
|
||||
roomid_inviteviaservers: db.roomid_inviteviaservers.clone(),
|
||||
roomuseroncejoinedids: db.roomuseroncejoinedids.clone(),
|
||||
roomid_joinedcount: db.roomid_joinedcount.clone(),
|
||||
roomid_invitedcount: db.roomid_invitedcount.clone(),
|
||||
roomserverids: db.roomserverids.clone(),
|
||||
serverroomids: db.serverroomids.clone(),
|
||||
db: db.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn mark_as_once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
let mut userroom_id = user_id.as_bytes().to_vec();
|
||||
userroom_id.push(0xFF);
|
||||
userroom_id.extend_from_slice(room_id.as_bytes());
|
||||
self.roomuseroncejoinedids.insert(&userroom_id, &[])
|
||||
}
|
||||
|
||||
fn mark_as_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
pub(super) fn mark_as_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
let roomid = room_id.as_bytes().to_vec();
|
||||
|
||||
let mut roomuser_id = roomid.clone();
|
||||
|
@ -134,7 +86,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn mark_as_invited(
|
||||
pub(super) fn mark_as_invited(
|
||||
&self, user_id: &UserId, room_id: &RoomId, last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
|
||||
invite_via: Option<Vec<OwnedServerName>>,
|
||||
) -> Result<()> {
|
||||
|
@ -179,7 +131,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn mark_as_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
pub(super) fn mark_as_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
let roomid = room_id.as_bytes().to_vec();
|
||||
|
||||
let mut roomuser_id = roomid.clone();
|
||||
|
@ -206,7 +158,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn update_joined_count(&self, room_id: &RoomId) -> Result<()> {
|
||||
pub(super) fn update_joined_count(&self, room_id: &RoomId) -> Result<()> {
|
||||
let mut joinedcount = 0_u64;
|
||||
let mut invitedcount = 0_u64;
|
||||
let mut joined_servers = HashSet::new();
|
||||
|
@ -256,7 +208,8 @@ impl Data for KeyValueDatabase {
|
|||
self.serverroomids.insert(&serverroom_id, &[])?;
|
||||
}
|
||||
|
||||
self.appservice_in_room_cache
|
||||
self.db
|
||||
.appservice_in_room_cache
|
||||
.write()
|
||||
.unwrap()
|
||||
.remove(room_id);
|
||||
|
@ -265,8 +218,9 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self, room_id, appservice))]
|
||||
fn appservice_in_room(&self, room_id: &RoomId, appservice: &RegistrationInfo) -> Result<bool> {
|
||||
pub(super) fn appservice_in_room(&self, room_id: &RoomId, appservice: &RegistrationInfo) -> Result<bool> {
|
||||
let maybe = self
|
||||
.db
|
||||
.appservice_in_room_cache
|
||||
.read()
|
||||
.unwrap()
|
||||
|
@ -288,7 +242,8 @@ impl Data for KeyValueDatabase {
|
|||
.room_members(room_id)
|
||||
.any(|userid| userid.map_or(false, |userid| appservice.users.is_match(userid.as_str())));
|
||||
|
||||
self.appservice_in_room_cache
|
||||
self.db
|
||||
.appservice_in_room_cache
|
||||
.write()
|
||||
.unwrap()
|
||||
.entry(room_id.to_owned())
|
||||
|
@ -301,7 +256,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Makes a user forget a room.
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn forget(&self, room_id: &RoomId, user_id: &UserId) -> Result<()> {
|
||||
pub(super) fn forget(&self, room_id: &RoomId, user_id: &UserId) -> Result<()> {
|
||||
let mut userroom_id = user_id.as_bytes().to_vec();
|
||||
userroom_id.push(0xFF);
|
||||
userroom_id.extend_from_slice(room_id.as_bytes());
|
||||
|
@ -318,7 +273,9 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns an iterator of all servers participating in this room.
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn room_servers<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedServerName>> + 'a> {
|
||||
pub(super) fn room_servers<'a>(
|
||||
&'a self, room_id: &RoomId,
|
||||
) -> Box<dyn Iterator<Item = Result<OwnedServerName>> + 'a> {
|
||||
let mut prefix = room_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -336,7 +293,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn server_in_room(&self, server: &ServerName, room_id: &RoomId) -> Result<bool> {
|
||||
pub(super) fn server_in_room(&self, server: &ServerName, room_id: &RoomId) -> Result<bool> {
|
||||
let mut key = server.as_bytes().to_vec();
|
||||
key.push(0xFF);
|
||||
key.extend_from_slice(room_id.as_bytes());
|
||||
|
@ -347,7 +304,9 @@ impl Data for KeyValueDatabase {
|
|||
/// Returns an iterator of all rooms a server participates in (as far as we
|
||||
/// know).
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn server_rooms<'a>(&'a self, server: &ServerName) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
|
||||
pub(super) fn server_rooms<'a>(
|
||||
&'a self, server: &ServerName,
|
||||
) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a> {
|
||||
let mut prefix = server.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -366,7 +325,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns an iterator of all joined members of a room.
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn room_members<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a> {
|
||||
pub(super) fn room_members<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a> {
|
||||
let mut prefix = room_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -385,7 +344,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns an iterator of all our local users in the room, even if they're
|
||||
/// deactivated/guests
|
||||
fn local_users_in_room<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = OwnedUserId> + 'a> {
|
||||
pub(super) fn local_users_in_room<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = OwnedUserId> + 'a> {
|
||||
Box::new(
|
||||
self.room_members(room_id)
|
||||
.filter_map(Result::ok)
|
||||
|
@ -396,7 +355,9 @@ impl Data for KeyValueDatabase {
|
|||
/// Returns an iterator of all our local joined users in a room who are
|
||||
/// active (not deactivated, not guest)
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn active_local_users_in_room<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = OwnedUserId> + 'a> {
|
||||
pub(super) fn active_local_users_in_room<'a>(
|
||||
&'a self, room_id: &RoomId,
|
||||
) -> Box<dyn Iterator<Item = OwnedUserId> + 'a> {
|
||||
Box::new(
|
||||
self.local_users_in_room(room_id)
|
||||
.filter(|user| !services().users.is_deactivated(user).unwrap_or(true)),
|
||||
|
@ -405,7 +366,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns the number of users which are currently in a room
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn room_joined_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||
pub(super) fn room_joined_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||
self.roomid_joinedcount
|
||||
.get(room_id.as_bytes())?
|
||||
.map(|b| utils::u64_from_bytes(&b).map_err(|_| Error::bad_database("Invalid joinedcount in db.")))
|
||||
|
@ -414,7 +375,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns the number of users which are currently invited to a room
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn room_invited_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||
pub(super) fn room_invited_count(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
||||
self.roomid_invitedcount
|
||||
.get(room_id.as_bytes())?
|
||||
.map(|b| utils::u64_from_bytes(&b).map_err(|_| Error::bad_database("Invalid joinedcount in db.")))
|
||||
|
@ -423,7 +384,9 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns an iterator over all User IDs who ever joined a room.
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn room_useroncejoined<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a> {
|
||||
pub(super) fn room_useroncejoined<'a>(
|
||||
&'a self, room_id: &RoomId,
|
||||
) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a> {
|
||||
let mut prefix = room_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -446,7 +409,9 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns an iterator over all invited members of a room.
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn room_members_invited<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a> {
|
||||
pub(super) fn room_members_invited<'a>(
|
||||
&'a self, room_id: &RoomId,
|
||||
) -> Box<dyn Iterator<Item = Result<OwnedUserId>> + 'a> {
|
||||
let mut prefix = room_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -468,7 +433,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn get_invite_count(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
|
||||
pub(super) fn get_invite_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());
|
||||
|
@ -483,7 +448,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn get_left_count(&self, room_id: &RoomId, user_id: &UserId) -> Result<Option<u64>> {
|
||||
pub(super) fn get_left_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());
|
||||
|
@ -496,7 +461,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns an iterator over all rooms this user joined.
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn rooms_joined(&self, user_id: &UserId) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + '_> {
|
||||
pub(super) fn rooms_joined(&self, user_id: &UserId) -> Box<dyn Iterator<Item = Result<OwnedRoomId>> + '_> {
|
||||
Box::new(
|
||||
self.userroomid_joined
|
||||
.scan_prefix(user_id.as_bytes().to_vec())
|
||||
|
@ -516,7 +481,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns an iterator over all rooms a user was invited to.
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn rooms_invited<'a>(&'a self, user_id: &UserId) -> StrippedStateEventIter<'a> {
|
||||
pub(super) fn rooms_invited<'a>(&'a self, user_id: &UserId) -> StrippedStateEventIter<'a> {
|
||||
let mut prefix = user_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -543,7 +508,9 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn invite_state(&self, user_id: &UserId, room_id: &RoomId) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
|
||||
pub(super) fn invite_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());
|
||||
|
@ -560,7 +527,9 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn left_state(&self, user_id: &UserId, room_id: &RoomId) -> Result<Option<Vec<Raw<AnyStrippedStateEvent>>>> {
|
||||
pub(super) fn left_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());
|
||||
|
@ -578,7 +547,7 @@ impl Data for KeyValueDatabase {
|
|||
|
||||
/// Returns an iterator over all rooms a user left.
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn rooms_left<'a>(&'a self, user_id: &UserId) -> AnySyncStateEventIter<'a> {
|
||||
pub(super) fn rooms_left<'a>(&'a self, user_id: &UserId) -> AnySyncStateEventIter<'a> {
|
||||
let mut prefix = user_id.as_bytes().to_vec();
|
||||
prefix.push(0xFF);
|
||||
|
||||
|
@ -605,7 +574,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
|
||||
pub(super) fn once_joined(&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());
|
||||
|
@ -614,7 +583,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn is_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
|
||||
pub(super) fn is_joined(&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());
|
||||
|
@ -623,7 +592,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn is_invited(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
|
||||
pub(super) fn is_invited(&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());
|
||||
|
@ -632,7 +601,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<bool> {
|
||||
pub(super) fn is_left(&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());
|
||||
|
@ -641,7 +610,9 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn servers_invite_via<'a>(&'a self, room_id: &RoomId) -> Box<dyn Iterator<Item = Result<OwnedServerName>> + 'a> {
|
||||
pub(super) fn servers_invite_via<'a>(
|
||||
&'a self, room_id: &RoomId,
|
||||
) -> Box<dyn Iterator<Item = Result<OwnedServerName>> + 'a> {
|
||||
let key = room_id.as_bytes().to_vec();
|
||||
|
||||
Box::new(
|
||||
|
@ -665,7 +636,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn add_servers_invite_via(&self, room_id: &RoomId, servers: &[OwnedServerName]) -> Result<()> {
|
||||
pub(super) fn add_servers_invite_via(&self, room_id: &RoomId, servers: &[OwnedServerName]) -> Result<()> {
|
||||
let mut prev_servers = self
|
||||
.servers_invite_via(room_id)
|
||||
.filter_map(Result::ok)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use conduit::Server;
|
||||
use data::Data;
|
||||
use database::KeyValueDatabase;
|
||||
use itertools::Itertools;
|
||||
use ruma::{
|
||||
events::{
|
||||
|
@ -24,10 +26,16 @@ use crate::{service::appservice::RegistrationInfo, services, user_is_local, Erro
|
|||
mod data;
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
/// Update current membership data.
|
||||
#[tracing::instrument(skip(self, last_state))]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
use std::{collections::HashSet, mem::size_of, sync::Arc};
|
||||
|
||||
use database::KvTree;
|
||||
|
||||
use super::CompressedStateEvent;
|
||||
use crate::{utils, Error, KeyValueDatabase, Result};
|
||||
|
||||
pub struct StateDiff {
|
||||
pub parent: Option<u64>,
|
||||
pub added: Arc<HashSet<CompressedStateEvent>>,
|
||||
pub removed: Arc<HashSet<CompressedStateEvent>>,
|
||||
pub(super) struct StateDiff {
|
||||
pub(super) parent: Option<u64>,
|
||||
pub(super) added: Arc<HashSet<CompressedStateEvent>>,
|
||||
pub(super) removed: Arc<HashSet<CompressedStateEvent>>,
|
||||
}
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn get_statediff(&self, shortstatehash: u64) -> Result<StateDiff>;
|
||||
fn save_statediff(&self, shortstatehash: u64, diff: StateDiff) -> Result<()>;
|
||||
pub struct Data {
|
||||
shortstatehash_statediff: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn get_statediff(&self, shortstatehash: u64) -> Result<StateDiff> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
shortstatehash_statediff: db.shortstatehash_statediff.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_statediff(&self, shortstatehash: u64) -> Result<StateDiff> {
|
||||
let value = self
|
||||
.shortstatehash_statediff
|
||||
.get(&shortstatehash.to_be_bytes())?
|
||||
|
@ -53,7 +60,7 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn save_statediff(&self, shortstatehash: u64, diff: StateDiff) -> Result<()> {
|
||||
pub(super) fn save_statediff(&self, shortstatehash: u64, diff: StateDiff) -> Result<()> {
|
||||
let mut value = diff.parent.unwrap_or(0).to_be_bytes().to_vec();
|
||||
for new in diff.added.iter() {
|
||||
value.extend_from_slice(&new[..]);
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
use std::sync::Mutex as StdMutex;
|
||||
|
||||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
|
@ -41,16 +46,25 @@ type ParentStatesVec = Vec<(
|
|||
)>;
|
||||
|
||||
type HashSetCompressStateEvent = Result<(u64, Arc<HashSet<CompressedStateEvent>>, Arc<HashSet<CompressedStateEvent>>)>;
|
||||
pub type CompressedStateEvent = [u8; 2 * size_of::<u64>()];
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
|
||||
pub stateinfo_cache: StateInfoLruCache,
|
||||
}
|
||||
|
||||
pub type CompressedStateEvent = [u8; 2 * size_of::<u64>()];
|
||||
|
||||
impl Service {
|
||||
pub fn build(server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
let config = &server.config;
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
stateinfo_cache: StdMutex::new(LruCache::new(
|
||||
(f64::from(config.stateinfo_cache_capacity) * config.conduit_cache_capacity_modifier) as usize,
|
||||
)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a stack with info on shortstatehash, full state, added diff and
|
||||
/// removed diff for the selected shortstatehash and each parent layer.
|
||||
#[tracing::instrument(skip(self))]
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
use std::mem::size_of;
|
||||
use std::{mem::size_of, sync::Arc};
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{api::client::threads::get_threads::v1::IncludeThreads, OwnedUserId, RoomId, UserId};
|
||||
|
||||
use crate::{services, utils, Error, KeyValueDatabase, PduEvent, Result};
|
||||
|
||||
type PduEventIterResult<'a> = Result<Box<dyn Iterator<Item = Result<(u64, PduEvent)>> + 'a>>;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn threads_until<'a>(
|
||||
&'a self, user_id: &'a UserId, room_id: &'a RoomId, until: u64, include: &'a IncludeThreads,
|
||||
) -> PduEventIterResult<'a>;
|
||||
|
||||
fn update_participants(&self, root_id: &[u8], participants: &[OwnedUserId]) -> Result<()>;
|
||||
fn get_participants(&self, root_id: &[u8]) -> Result<Option<Vec<OwnedUserId>>>;
|
||||
pub struct Data {
|
||||
threadid_userids: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn threads_until<'a>(
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
threadid_userids: db.threadid_userids.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn threads_until<'a>(
|
||||
&'a self, user_id: &'a UserId, room_id: &'a RoomId, until: u64, _include: &'a IncludeThreads,
|
||||
) -> PduEventIterResult<'a> {
|
||||
let prefix = services()
|
||||
|
@ -50,7 +52,7 @@ impl Data for KeyValueDatabase {
|
|||
))
|
||||
}
|
||||
|
||||
fn update_participants(&self, root_id: &[u8], participants: &[OwnedUserId]) -> Result<()> {
|
||||
pub(super) fn update_participants(&self, root_id: &[u8], participants: &[OwnedUserId]) -> Result<()> {
|
||||
let users = participants
|
||||
.iter()
|
||||
.map(|user| user.as_bytes())
|
||||
|
@ -62,7 +64,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_participants(&self, root_id: &[u8]) -> Result<Option<Vec<OwnedUserId>>> {
|
||||
pub(super) fn get_participants(&self, root_id: &[u8]) -> Result<Option<Vec<OwnedUserId>>> {
|
||||
if let Some(users) = self.threadid_userids.get(root_id)? {
|
||||
Ok(Some(
|
||||
users
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
|
@ -13,10 +16,16 @@ use serde_json::json;
|
|||
use crate::{services, Error, PduEvent, Result};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn threads_until<'a>(
|
||||
&'a self, user_id: &'a UserId, room_id: &'a RoomId, until: u64, include: &'a IncludeThreads,
|
||||
) -> Result<impl Iterator<Item = Result<(u64, PduEvent)>> + 'a> {
|
||||
|
|
|
@ -1,76 +1,36 @@
|
|||
use std::{collections::hash_map, mem::size_of, sync::Arc};
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{api::client::error::ErrorKind, CanonicalJsonObject, EventId, OwnedUserId, RoomId, UserId};
|
||||
use tracing::error;
|
||||
|
||||
use super::PduCount;
|
||||
use crate::{services, utils, Error, KeyValueDatabase, PduEvent, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn last_timeline_count(&self, sender_user: &UserId, room_id: &RoomId) -> Result<PduCount>;
|
||||
|
||||
/// Returns the `count` of this pdu's id.
|
||||
fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<PduCount>>;
|
||||
|
||||
/// Returns the json of a pdu.
|
||||
fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>>;
|
||||
|
||||
/// Returns the json of a pdu.
|
||||
fn get_non_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>>;
|
||||
|
||||
/// Returns the pdu's id.
|
||||
fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>>;
|
||||
|
||||
/// Returns the pdu.
|
||||
///
|
||||
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
||||
fn get_non_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>>;
|
||||
|
||||
/// Returns the pdu.
|
||||
///
|
||||
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
||||
fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>>;
|
||||
|
||||
/// Returns the pdu.
|
||||
///
|
||||
/// This does __NOT__ check the outliers `Tree`.
|
||||
fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>>;
|
||||
|
||||
/// Returns the pdu as a `BTreeMap<String, CanonicalJsonValue>`.
|
||||
fn get_pdu_json_from_id(&self, pdu_id: &[u8]) -> Result<Option<CanonicalJsonObject>>;
|
||||
|
||||
/// Adds a new pdu to the timeline
|
||||
fn append_pdu(&self, pdu_id: &[u8], pdu: &PduEvent, json: &CanonicalJsonObject, count: u64) -> Result<()>;
|
||||
|
||||
// Adds a new pdu to the backfilled timeline
|
||||
fn prepend_backfill_pdu(&self, pdu_id: &[u8], event_id: &EventId, json: &CanonicalJsonObject) -> Result<()>;
|
||||
|
||||
/// Removes a pdu and creates a new one with the same id.
|
||||
fn replace_pdu(&self, pdu_id: &[u8], pdu_json: &CanonicalJsonObject, pdu: &PduEvent) -> Result<()>;
|
||||
|
||||
/// Returns an iterator over all events and their tokens in a room that
|
||||
/// happened before the event with id `until` in reverse-chronological
|
||||
/// order.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn pdus_until<'a>(
|
||||
&'a self, user_id: &UserId, room_id: &RoomId, until: PduCount,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<(PduCount, PduEvent)>> + 'a>>;
|
||||
|
||||
/// Returns an iterator over all events in a room that happened after the
|
||||
/// event with id `from` in chronological order.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn pdus_after<'a>(
|
||||
&'a self, user_id: &UserId, room_id: &RoomId, from: PduCount,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<(PduCount, PduEvent)>> + 'a>>;
|
||||
|
||||
fn increment_notification_counts(
|
||||
&self, room_id: &RoomId, notifies: Vec<OwnedUserId>, highlights: Vec<OwnedUserId>,
|
||||
) -> Result<()>;
|
||||
pub struct Data {
|
||||
eventid_pduid: Arc<dyn KvTree>,
|
||||
pduid_pdu: Arc<dyn KvTree>,
|
||||
eventid_outlierpdu: Arc<dyn KvTree>,
|
||||
userroomid_notificationcount: Arc<dyn KvTree>,
|
||||
userroomid_highlightcount: Arc<dyn KvTree>,
|
||||
db: Arc<KeyValueDatabase>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn last_timeline_count(&self, sender_user: &UserId, room_id: &RoomId) -> Result<PduCount> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
eventid_pduid: db.eventid_pduid.clone(),
|
||||
pduid_pdu: db.pduid_pdu.clone(),
|
||||
eventid_outlierpdu: db.eventid_outlierpdu.clone(),
|
||||
userroomid_notificationcount: db.userroomid_notificationcount.clone(),
|
||||
userroomid_highlightcount: db.userroomid_highlightcount.clone(),
|
||||
db: db.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn last_timeline_count(&self, sender_user: &UserId, room_id: &RoomId) -> Result<PduCount> {
|
||||
match self
|
||||
.db
|
||||
.lasttimelinecount_cache
|
||||
.lock()
|
||||
.unwrap()
|
||||
|
@ -96,7 +56,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Returns the `count` of this pdu's id.
|
||||
fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<PduCount>> {
|
||||
pub(super) fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<PduCount>> {
|
||||
self.eventid_pduid
|
||||
.get(event_id.as_bytes())?
|
||||
.map(|pdu_id| pdu_count(&pdu_id))
|
||||
|
@ -104,7 +64,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Returns the json of a pdu.
|
||||
fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
|
||||
pub(super) fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
|
||||
self.get_non_outlier_pdu_json(event_id)?.map_or_else(
|
||||
|| {
|
||||
self.eventid_outlierpdu
|
||||
|
@ -117,7 +77,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Returns the json of a pdu.
|
||||
fn get_non_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
|
||||
pub(super) fn get_non_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
|
||||
self.eventid_pduid
|
||||
.get(event_id.as_bytes())?
|
||||
.map(|pduid| {
|
||||
|
@ -131,10 +91,12 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Returns the pdu's id.
|
||||
fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>> { self.eventid_pduid.get(event_id.as_bytes()) }
|
||||
pub(super) fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>> {
|
||||
self.eventid_pduid.get(event_id.as_bytes())
|
||||
}
|
||||
|
||||
/// Returns the pdu.
|
||||
fn get_non_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>> {
|
||||
pub(super) fn get_non_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>> {
|
||||
self.eventid_pduid
|
||||
.get(event_id.as_bytes())?
|
||||
.map(|pduid| {
|
||||
|
@ -150,7 +112,7 @@ impl Data for KeyValueDatabase {
|
|||
/// Returns the pdu.
|
||||
///
|
||||
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
|
||||
fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> {
|
||||
pub(super) fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> {
|
||||
if let Some(pdu) = self
|
||||
.get_non_outlier_pdu(event_id)?
|
||||
.map_or_else(
|
||||
|
@ -173,7 +135,7 @@ impl Data for KeyValueDatabase {
|
|||
/// Returns the pdu.
|
||||
///
|
||||
/// This does __NOT__ check the outliers `Tree`.
|
||||
fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>> {
|
||||
pub(super) fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>> {
|
||||
self.pduid_pdu.get(pdu_id)?.map_or(Ok(None), |pdu| {
|
||||
Ok(Some(
|
||||
serde_json::from_slice(&pdu).map_err(|_| Error::bad_database("Invalid PDU in db."))?,
|
||||
|
@ -182,7 +144,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Returns the pdu as a `BTreeMap<String, CanonicalJsonValue>`.
|
||||
fn get_pdu_json_from_id(&self, pdu_id: &[u8]) -> Result<Option<CanonicalJsonObject>> {
|
||||
pub(super) fn get_pdu_json_from_id(&self, pdu_id: &[u8]) -> Result<Option<CanonicalJsonObject>> {
|
||||
self.pduid_pdu.get(pdu_id)?.map_or(Ok(None), |pdu| {
|
||||
Ok(Some(
|
||||
serde_json::from_slice(&pdu).map_err(|_| Error::bad_database("Invalid PDU in db."))?,
|
||||
|
@ -190,13 +152,16 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn append_pdu(&self, pdu_id: &[u8], pdu: &PduEvent, json: &CanonicalJsonObject, count: u64) -> Result<()> {
|
||||
pub(super) fn append_pdu(
|
||||
&self, pdu_id: &[u8], pdu: &PduEvent, json: &CanonicalJsonObject, count: u64,
|
||||
) -> Result<()> {
|
||||
self.pduid_pdu.insert(
|
||||
pdu_id,
|
||||
&serde_json::to_vec(json).expect("CanonicalJsonObject is always a valid"),
|
||||
)?;
|
||||
|
||||
self.lasttimelinecount_cache
|
||||
self.db
|
||||
.lasttimelinecount_cache
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(pdu.room_id.clone(), PduCount::Normal(count));
|
||||
|
@ -207,7 +172,9 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn prepend_backfill_pdu(&self, pdu_id: &[u8], event_id: &EventId, json: &CanonicalJsonObject) -> Result<()> {
|
||||
pub(super) fn prepend_backfill_pdu(
|
||||
&self, pdu_id: &[u8], event_id: &EventId, json: &CanonicalJsonObject,
|
||||
) -> Result<()> {
|
||||
self.pduid_pdu.insert(
|
||||
pdu_id,
|
||||
&serde_json::to_vec(json).expect("CanonicalJsonObject is always a valid"),
|
||||
|
@ -220,7 +187,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Removes a pdu and creates a new one with the same id.
|
||||
fn replace_pdu(&self, pdu_id: &[u8], pdu_json: &CanonicalJsonObject, _pdu: &PduEvent) -> Result<()> {
|
||||
pub(super) fn replace_pdu(&self, pdu_id: &[u8], pdu_json: &CanonicalJsonObject, _pdu: &PduEvent) -> Result<()> {
|
||||
if self.pduid_pdu.get(pdu_id)?.is_some() {
|
||||
self.pduid_pdu.insert(
|
||||
pdu_id,
|
||||
|
@ -236,7 +203,7 @@ impl Data for KeyValueDatabase {
|
|||
/// Returns an iterator over all events and their tokens in a room that
|
||||
/// happened before the event with id `until` in reverse-chronological
|
||||
/// order.
|
||||
fn pdus_until<'a>(
|
||||
pub(super) fn pdus_until<'a>(
|
||||
&'a self, user_id: &UserId, room_id: &RoomId, until: PduCount,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<(PduCount, PduEvent)>> + 'a>> {
|
||||
let (prefix, current) = count_to_id(room_id, until, 1, true)?;
|
||||
|
@ -260,7 +227,7 @@ impl Data for KeyValueDatabase {
|
|||
))
|
||||
}
|
||||
|
||||
fn pdus_after<'a>(
|
||||
pub(super) fn pdus_after<'a>(
|
||||
&'a self, user_id: &UserId, room_id: &RoomId, from: PduCount,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<(PduCount, PduEvent)>> + 'a>> {
|
||||
let (prefix, current) = count_to_id(room_id, from, 1, false)?;
|
||||
|
@ -284,7 +251,7 @@ impl Data for KeyValueDatabase {
|
|||
))
|
||||
}
|
||||
|
||||
fn increment_notification_counts(
|
||||
pub(super) fn increment_notification_counts(
|
||||
&self, room_id: &RoomId, notifies: Vec<OwnedUserId>, highlights: Vec<OwnedUserId>,
|
||||
) -> Result<()> {
|
||||
let mut notifies_batch = Vec::new();
|
||||
|
@ -311,7 +278,7 @@ impl Data for KeyValueDatabase {
|
|||
}
|
||||
|
||||
/// Returns the `count` of this pdu's id.
|
||||
fn pdu_count(pdu_id: &[u8]) -> Result<PduCount> {
|
||||
pub(super) fn pdu_count(pdu_id: &[u8]) -> Result<PduCount> {
|
||||
let last_u64 = utils::u64_from_bytes(&pdu_id[pdu_id.len() - size_of::<u64>()..])
|
||||
.map_err(|_| Error::bad_database("PDU has invalid count bytes."))?;
|
||||
let second_last_u64 =
|
||||
|
@ -324,7 +291,9 @@ fn pdu_count(pdu_id: &[u8]) -> Result<PduCount> {
|
|||
}
|
||||
}
|
||||
|
||||
fn count_to_id(room_id: &RoomId, count: PduCount, offset: u64, subtract: bool) -> Result<(Vec<u8>, Vec<u8>)> {
|
||||
pub(super) fn count_to_id(
|
||||
room_id: &RoomId, count: PduCount, offset: u64, subtract: bool,
|
||||
) -> Result<(Vec<u8>, Vec<u8>)> {
|
||||
let prefix = services()
|
||||
.rooms
|
||||
.short
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::{
|
||||
|
@ -74,12 +77,19 @@ struct ExtractBody {
|
|||
}
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
|
||||
pub lasttimelinecount_cache: Mutex<HashMap<OwnedRoomId, PduCount>>,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
lasttimelinecount_cache: Mutex::new(HashMap::new()),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn first_pdu_in_room(&self, room_id: &RoomId) -> Result<Option<Arc<PduEvent>>> {
|
||||
self.all_pdus(user_id!("@doesntmatter:conduit.rs"), room_id)?
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
|
||||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
use ruma::{
|
||||
api::federation::transactions::edu::{Edu, TypingContent},
|
||||
events::SyncEphemeralRoomEvent,
|
||||
|
@ -23,6 +25,14 @@ pub struct Service {
|
|||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, _db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
typing: RwLock::new(BTreeMap::new()),
|
||||
last_typing_update: RwLock::new(BTreeMap::new()),
|
||||
typing_update_sender: broadcast::channel(100).0,
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets a user as typing until the timeout timestamp is reached or
|
||||
/// roomtyping_remove is called.
|
||||
pub async fn typing_add(&self, user_id: &UserId, room_id: &RoomId, timeout: u64) -> Result<()> {
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use database::KvTree;
|
||||
use ruma::{OwnedRoomId, OwnedUserId, RoomId, UserId};
|
||||
|
||||
use crate::{services, utils, Error, KeyValueDatabase, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn reset_notification_counts(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
|
||||
fn notification_count(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64>;
|
||||
|
||||
fn highlight_count(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64>;
|
||||
|
||||
// Returns the count at which the last reset_notification_counts was called
|
||||
fn last_notification_read(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64>;
|
||||
|
||||
fn associate_token_shortstatehash(&self, room_id: &RoomId, token: u64, shortstatehash: u64) -> Result<()>;
|
||||
|
||||
fn get_token_shortstatehash(&self, room_id: &RoomId, token: u64) -> Result<Option<u64>>;
|
||||
|
||||
fn get_shared_rooms<'a>(
|
||||
&'a self, users: Vec<OwnedUserId>,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a>>;
|
||||
pub struct Data {
|
||||
userroomid_notificationcount: Arc<dyn KvTree>,
|
||||
userroomid_highlightcount: Arc<dyn KvTree>,
|
||||
roomuserid_lastnotificationread: Arc<dyn KvTree>,
|
||||
roomsynctoken_shortstatehash: Arc<dyn KvTree>,
|
||||
userroomid_joined: Arc<dyn KvTree>,
|
||||
}
|
||||
|
||||
impl Data for KeyValueDatabase {
|
||||
fn reset_notification_counts(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
impl Data {
|
||||
pub(super) fn new(db: &Arc<KeyValueDatabase>) -> Self {
|
||||
Self {
|
||||
userroomid_notificationcount: db.userroomid_notificationcount.clone(),
|
||||
userroomid_highlightcount: db.userroomid_highlightcount.clone(),
|
||||
roomuserid_lastnotificationread: db.roomuserid_lastnotificationread.clone(),
|
||||
roomsynctoken_shortstatehash: db.roomsynctoken_shortstatehash.clone(),
|
||||
userroomid_joined: db.userroomid_joined.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn reset_notification_counts(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
let mut userroom_id = user_id.as_bytes().to_vec();
|
||||
userroom_id.push(0xFF);
|
||||
userroom_id.extend_from_slice(room_id.as_bytes());
|
||||
|
@ -41,7 +43,7 @@ impl Data for KeyValueDatabase {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn notification_count(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||
pub(super) fn notification_count(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||
let mut userroom_id = user_id.as_bytes().to_vec();
|
||||
userroom_id.push(0xFF);
|
||||
userroom_id.extend_from_slice(room_id.as_bytes());
|
||||
|
@ -53,7 +55,7 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn highlight_count(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||
pub(super) fn highlight_count(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||
let mut userroom_id = user_id.as_bytes().to_vec();
|
||||
userroom_id.push(0xFF);
|
||||
userroom_id.extend_from_slice(room_id.as_bytes());
|
||||
|
@ -65,7 +67,7 @@ impl Data for KeyValueDatabase {
|
|||
})
|
||||
}
|
||||
|
||||
fn last_notification_read(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||
pub(super) fn last_notification_read(&self, user_id: &UserId, room_id: &RoomId) -> Result<u64> {
|
||||
let mut key = room_id.as_bytes().to_vec();
|
||||
key.push(0xFF);
|
||||
key.extend_from_slice(user_id.as_bytes());
|
||||
|
@ -81,7 +83,9 @@ impl Data for KeyValueDatabase {
|
|||
.unwrap_or(0))
|
||||
}
|
||||
|
||||
fn associate_token_shortstatehash(&self, room_id: &RoomId, token: u64, shortstatehash: u64) -> Result<()> {
|
||||
pub(super) fn associate_token_shortstatehash(
|
||||
&self, room_id: &RoomId, token: u64, shortstatehash: u64,
|
||||
) -> Result<()> {
|
||||
let shortroomid = services()
|
||||
.rooms
|
||||
.short
|
||||
|
@ -95,7 +99,7 @@ impl Data for KeyValueDatabase {
|
|||
.insert(&key, &shortstatehash.to_be_bytes())
|
||||
}
|
||||
|
||||
fn get_token_shortstatehash(&self, room_id: &RoomId, token: u64) -> Result<Option<u64>> {
|
||||
pub(super) fn get_token_shortstatehash(&self, room_id: &RoomId, token: u64) -> Result<Option<u64>> {
|
||||
let shortroomid = services()
|
||||
.rooms
|
||||
.short
|
||||
|
@ -114,7 +118,7 @@ impl Data for KeyValueDatabase {
|
|||
.transpose()
|
||||
}
|
||||
|
||||
fn get_shared_rooms<'a>(
|
||||
pub(super) fn get_shared_rooms<'a>(
|
||||
&'a self, users: Vec<OwnedUserId>,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<OwnedRoomId>> + 'a>> {
|
||||
let iterators = users.into_iter().map(move |user_id| {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use conduit::Server;
|
||||
use database::KeyValueDatabase;
|
||||
|
||||
mod data;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
@ -8,10 +11,16 @@ use ruma::{OwnedRoomId, OwnedUserId, RoomId, UserId};
|
|||
use crate::Result;
|
||||
|
||||
pub struct Service {
|
||||
pub db: Arc<dyn Data>,
|
||||
pub db: Data,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn build(_server: &Arc<Server>, db: &Arc<KeyValueDatabase>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
db: Data::new(db),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn reset_notification_counts(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
|
||||
self.db.reset_notification_counts(user_id, room_id)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue