Hot-Reloading Refactor

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-05-09 15:59:08 -07:00 committed by June 🍓🦴
parent ae1a4fd283
commit 6c1434c165
212 changed files with 5679 additions and 4206 deletions

View file

@ -1,12 +1,11 @@
pub(crate) mod data;
pub mod data;
use std::{
cmp::Ordering,
collections::{BTreeMap, HashMap, HashSet},
sync::Arc,
};
pub(crate) use data::Data;
pub use data::Data;
use rand::prelude::SliceRandom;
use ruma::{
api::{client::error::ErrorKind, federation},
@ -35,60 +34,22 @@ use tracing::{debug, error, info, warn};
use super::state_compressor::CompressedStateEvent;
use crate::{
api::server_server,
server_is_ours,
//api::server_server,
service::{
self,
appservice::NamespaceRegex,
pdu::{EventHash, PduBuilder},
rooms::event_handler::parse_incoming_pdu,
},
services,
utils::{self, server_name::server_is_ours},
Error, PduEvent, Result,
utils::{self},
Error,
PduCount,
PduEvent,
Result,
};
#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
pub(crate) enum PduCount {
Backfilled(u64),
Normal(u64),
}
impl PduCount {
pub(crate) fn min() -> Self { Self::Backfilled(u64::MAX) }
pub(crate) fn max() -> Self { Self::Normal(u64::MAX) }
pub(crate) fn try_from_string(token: &str) -> Result<Self> {
if let Some(stripped_token) = token.strip_prefix('-') {
stripped_token.parse().map(PduCount::Backfilled)
} else {
token.parse().map(PduCount::Normal)
}
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid pagination token."))
}
pub(crate) fn stringify(&self) -> String {
match self {
PduCount::Backfilled(x) => format!("-{x}"),
PduCount::Normal(x) => x.to_string(),
}
}
}
impl PartialOrd for PduCount {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}
impl Ord for PduCount {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(PduCount::Normal(s), PduCount::Normal(o)) => s.cmp(o),
(PduCount::Backfilled(s), PduCount::Backfilled(o)) => o.cmp(s),
(PduCount::Normal(_), PduCount::Backfilled(_)) => Ordering::Greater,
(PduCount::Backfilled(_), PduCount::Normal(_)) => Ordering::Less,
}
}
}
// Update Relationships
#[derive(Deserialize)]
struct ExtractRelatesTo {
@ -106,15 +67,15 @@ struct ExtractRelatesToEventId {
relates_to: ExtractEventId,
}
pub(crate) struct Service {
pub(crate) db: &'static dyn Data,
pub struct Service {
pub db: Arc<dyn Data>,
pub(crate) lasttimelinecount_cache: Mutex<HashMap<OwnedRoomId, PduCount>>,
pub lasttimelinecount_cache: Mutex<HashMap<OwnedRoomId, PduCount>>,
}
impl Service {
#[tracing::instrument(skip(self))]
pub(crate) fn first_pdu_in_room(&self, room_id: &RoomId) -> Result<Option<Arc<PduEvent>>> {
pub fn first_pdu_in_room(&self, room_id: &RoomId) -> Result<Option<Arc<PduEvent>>> {
self.all_pdus(user_id!("@doesntmatter:conduit.rs"), room_id)?
.next()
.map(|o| o.map(|(_, p)| Arc::new(p)))
@ -122,19 +83,17 @@ impl Service {
}
#[tracing::instrument(skip(self))]
pub(crate) fn last_timeline_count(&self, sender_user: &UserId, room_id: &RoomId) -> Result<PduCount> {
pub fn last_timeline_count(&self, sender_user: &UserId, room_id: &RoomId) -> Result<PduCount> {
self.db.last_timeline_count(sender_user, room_id)
}
/// Returns the `count` of this pdu's id.
pub(crate) fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<PduCount>> {
self.db.get_pdu_count(event_id)
}
pub fn get_pdu_count(&self, event_id: &EventId) -> Result<Option<PduCount>> { self.db.get_pdu_count(event_id) }
// TODO Is this the same as the function above?
/*
#[tracing::instrument(skip(self))]
pub(crate) fn latest_pdu_count(&self, room_id: &RoomId) -> Result<u64> {
pub fn latest_pdu_count(&self, room_id: &RoomId) -> Result<u64> {
let prefix = self
.get_shortroomid(room_id)?
.expect("room exists")
@ -158,7 +117,7 @@ impl Service {
///
/// TODO: use this?
#[allow(dead_code)]
pub(crate) fn get_room_version(&self, room_id: &RoomId) -> Result<Option<RoomVersionId>> {
pub fn get_room_version(&self, room_id: &RoomId) -> Result<Option<RoomVersionId>> {
let create_event = services()
.rooms
.state_accessor
@ -178,17 +137,17 @@ impl Service {
}
/// Returns the json of a pdu.
pub(crate) fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
pub fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
self.db.get_pdu_json(event_id)
}
/// Returns the json of a pdu.
pub(crate) fn get_non_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
pub fn get_non_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>> {
self.db.get_non_outlier_pdu_json(event_id)
}
/// Returns the pdu's id.
pub(crate) fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>> { self.db.get_pdu_id(event_id) }
pub fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>> { self.db.get_pdu_id(event_id) }
/// Returns the pdu.
///
@ -196,28 +155,28 @@ impl Service {
///
/// TODO: use this?
#[allow(dead_code)]
pub(crate) fn get_non_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>> {
pub fn get_non_outlier_pdu(&self, event_id: &EventId) -> Result<Option<PduEvent>> {
self.db.get_non_outlier_pdu(event_id)
}
/// Returns the pdu.
///
/// Checks the `eventid_outlierpdu` Tree if not found in the timeline.
pub(crate) fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> { self.db.get_pdu(event_id) }
pub fn get_pdu(&self, event_id: &EventId) -> Result<Option<Arc<PduEvent>>> { self.db.get_pdu(event_id) }
/// Returns the pdu.
///
/// This does __NOT__ check the outliers `Tree`.
pub(crate) fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>> { self.db.get_pdu_from_id(pdu_id) }
pub fn get_pdu_from_id(&self, pdu_id: &[u8]) -> Result<Option<PduEvent>> { self.db.get_pdu_from_id(pdu_id) }
/// Returns the pdu as a `BTreeMap<String, CanonicalJsonValue>`.
pub(crate) fn get_pdu_json_from_id(&self, pdu_id: &[u8]) -> Result<Option<CanonicalJsonObject>> {
pub fn get_pdu_json_from_id(&self, pdu_id: &[u8]) -> Result<Option<CanonicalJsonObject>> {
self.db.get_pdu_json_from_id(pdu_id)
}
/// Removes a pdu and creates a new one with the same id.
#[tracing::instrument(skip(self))]
pub(crate) fn replace_pdu(&self, pdu_id: &[u8], pdu_json: &CanonicalJsonObject, pdu: &PduEvent) -> Result<()> {
pub fn replace_pdu(&self, pdu_id: &[u8], pdu_json: &CanonicalJsonObject, pdu: &PduEvent) -> Result<()> {
self.db.replace_pdu(pdu_id, pdu_json, pdu)
}
@ -228,7 +187,7 @@ impl Service {
///
/// Returns pdu id
#[tracing::instrument(skip(self, pdu, pdu_json, leaves))]
pub(crate) async fn append_pdu(
pub async fn append_pdu(
&self,
pdu: &PduEvent,
mut pdu_json: CanonicalJsonObject,
@ -513,7 +472,6 @@ impl Service {
// This will evaluate to false if the emergency password is set up so that
// the administrator can execute commands as conduit
let from_conduit = pdu.sender == server_user && services().globals.emergency_password().is_none();
if let Some(admin_room) = service::admin::Service::get_admin_room().await? {
if to_conduit && !from_conduit && admin_room == pdu.room_id {
services()
@ -628,7 +586,7 @@ impl Service {
Ok(pdu_id)
}
pub(crate) fn create_hash_and_sign_event(
pub fn create_hash_and_sign_event(
&self,
pdu_builder: PduBuilder,
sender: &UserId,
@ -811,7 +769,7 @@ impl Service {
/// takes a roomid_mutex_state, meaning that only this function is able to
/// mutate the room state.
#[tracing::instrument(skip(self, state_lock))]
pub(crate) async fn build_and_append_pdu(
pub async fn build_and_append_pdu(
&self,
pdu_builder: PduBuilder,
sender: &UserId,
@ -819,7 +777,6 @@ impl Service {
state_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
) -> Result<Arc<EventId>> {
let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?;
if let Some(admin_room) = service::admin::Service::get_admin_room().await? {
if admin_room == room_id {
match pdu.event_type() {
@ -951,7 +908,7 @@ impl Service {
/// Append the incoming event setting the state snapshot to the state from
/// the server that sent the event.
#[tracing::instrument(skip_all)]
pub(crate) async fn append_incoming_pdu(
pub async fn append_incoming_pdu(
&self,
pdu: &PduEvent,
pdu_json: CanonicalJsonObject,
@ -990,7 +947,7 @@ impl Service {
}
/// Returns an iterator over all PDUs in a room.
pub(crate) fn all_pdus<'a>(
pub fn all_pdus<'a>(
&'a self, user_id: &UserId, room_id: &RoomId,
) -> Result<impl Iterator<Item = Result<(PduCount, PduEvent)>> + 'a> {
self.pdus_after(user_id, room_id, PduCount::min())
@ -1000,7 +957,7 @@ impl Service {
/// happened before the event with id `until` in reverse-chronological
/// order.
#[tracing::instrument(skip(self))]
pub(crate) fn pdus_until<'a>(
pub fn pdus_until<'a>(
&'a self, user_id: &UserId, room_id: &RoomId, until: PduCount,
) -> Result<impl Iterator<Item = Result<(PduCount, PduEvent)>> + 'a> {
self.db.pdus_until(user_id, room_id, until)
@ -1009,7 +966,7 @@ impl Service {
/// Returns an iterator over all events and their token in a room that
/// happened after the event with id `from` in chronological order.
#[tracing::instrument(skip(self))]
pub(crate) fn pdus_after<'a>(
pub fn pdus_after<'a>(
&'a self, user_id: &UserId, room_id: &RoomId, from: PduCount,
) -> Result<impl Iterator<Item = Result<(PduCount, PduEvent)>> + 'a> {
self.db.pdus_after(user_id, room_id, from)
@ -1017,7 +974,7 @@ impl Service {
/// Replace a PDU with the redacted form.
#[tracing::instrument(skip(self, reason))]
pub(crate) fn redact_pdu(&self, event_id: &EventId, reason: &PduEvent) -> Result<()> {
pub fn redact_pdu(&self, event_id: &EventId, reason: &PduEvent) -> Result<()> {
// TODO: Don't reserialize, keep original json
if let Some(pdu_id) = self.get_pdu_id(event_id)? {
let mut pdu = self
@ -1039,7 +996,7 @@ impl Service {
}
#[tracing::instrument(skip(self, room_id))]
pub(crate) async fn backfill_if_required(&self, room_id: &RoomId, from: PduCount) -> Result<()> {
pub async fn backfill_if_required(&self, room_id: &RoomId, from: PduCount) -> Result<()> {
let first_pdu = self
.all_pdus(user_id!("@doesntmatter:conduit.rs"), room_id)?
.next()
@ -1154,11 +1111,11 @@ impl Service {
}
#[tracing::instrument(skip(self, pdu, pub_key_map))]
pub(crate) async fn backfill_pdu(
pub async fn backfill_pdu(
&self, origin: &ServerName, pdu: Box<RawJsonValue>,
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
) -> Result<()> {
let (event_id, value, room_id) = server_server::parse_incoming_pdu(&pdu)?;
let (event_id, value, room_id) = parse_incoming_pdu(&pdu)?;
// Lock so we cannot backfill the same pdu twice at the same time
let mutex = Arc::clone(