refactor appservice type stuff

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
Matthias Ahouansou 2024-03-22 19:21:51 -04:00 committed by June
parent 7c9c5b1d78
commit 60f2471f59
11 changed files with 125 additions and 133 deletions

View file

@ -623,8 +623,8 @@ impl Service {
},
AppserviceCommand::Show {
appservice_identifier,
} => match services().appservice.get_registration(&appservice_identifier) {
Ok(Some(config)) => {
} => match services().appservice.get_registration(&appservice_identifier).await {
Some(config) => {
let config_str =
serde_yaml::to_string(&config).expect("config should've been validated on register");
let output = format!("Config for {}:\n\n```yaml\n{}\n```", appservice_identifier, config_str,);
@ -635,21 +635,12 @@ impl Service {
);
RoomMessageEventContent::text_html(output, output_html)
},
Ok(None) => RoomMessageEventContent::text_plain("Appservice does not exist."),
Err(_) => RoomMessageEventContent::text_plain("Failed to get appservice."),
None => RoomMessageEventContent::text_plain("Appservice does not exist."),
},
AppserviceCommand::List => {
if let Ok(appservices) = services().appservice.iter_ids().map(Iterator::collect::<Vec<_>>) {
let count = appservices.len();
let output = format!(
"Appservices ({}): {}",
count,
appservices.into_iter().filter_map(std::result::Result::ok).collect::<Vec<_>>().join(", ")
);
RoomMessageEventContent::text_plain(output)
} else {
RoomMessageEventContent::text_plain("Failed to get appservices.")
}
let appservices = services().appservice.iter_ids().await;
let output = format!("Appservices ({}): {}", appservices.len(), appservices.join(", "));
RoomMessageEventContent::text_plain(output)
},
},
AdminCommand::Media(command) => {

View file

@ -1,8 +1,9 @@
mod data;
use std::collections::HashMap;
use std::collections::BTreeMap;
pub(crate) use data::Data;
use futures_util::Future;
use regex::RegexSet;
use ruma::api::appservice::{Namespace, Registration};
use tokio::sync::RwLock;
@ -10,6 +11,7 @@ use tokio::sync::RwLock;
use crate::{services, Result};
/// Compiled regular expressions for a namespace
#[derive(Clone, Debug)]
pub struct NamespaceRegex {
pub exclusive: Option<RegexSet>,
pub non_exclusive: Option<RegexSet>,
@ -71,7 +73,8 @@ impl TryFrom<Vec<Namespace>> for NamespaceRegex {
}
}
/// Compiled regular expressions for an appservice
/// Appservice registration combined with its compiled regular expressions.
#[derive(Clone, Debug)]
pub struct RegistrationInfo {
pub registration: Registration,
pub users: NamespaceRegex,
@ -94,10 +97,26 @@ impl TryFrom<Registration> for RegistrationInfo {
pub struct Service {
pub db: &'static dyn Data,
pub registration_info: RwLock<HashMap<String, RegistrationInfo>>,
registration_info: RwLock<BTreeMap<String, RegistrationInfo>>,
}
impl Service {
pub fn build(db: &'static dyn Data) -> Result<Self> {
let mut registration_info = BTreeMap::new();
// Inserting registrations into cache
for appservice in db.all()? {
registration_info.insert(
appservice.0,
appservice.1.try_into().expect("Should be validated on registration"),
);
}
Ok(Self {
db,
registration_info: RwLock::new(registration_info),
})
}
/// Registers an appservice and returns the ID to the caller
pub async fn register_appservice(&self, yaml: Registration) -> Result<String> {
services().appservice.registration_info.write().await.insert(yaml.id.clone(), yaml.clone().try_into()?);
@ -116,9 +135,17 @@ impl Service {
self.db.unregister_appservice(service_name)
}
pub fn get_registration(&self, id: &str) -> Result<Option<Registration>> { self.db.get_registration(id) }
pub async fn get_registration(&self, id: &str) -> Option<Registration> {
self.registration_info.read().await.get(id).cloned().map(|info| info.registration)
}
pub fn iter_ids(&self) -> Result<impl Iterator<Item = Result<String>> + '_> { self.db.iter_ids() }
pub async fn iter_ids(&self) -> Vec<String> { self.registration_info.read().await.keys().cloned().collect() }
pub fn all(&self) -> Result<Vec<(String, Registration)>> { self.db.all() }
pub async fn find_from_token(&self, token: &str) -> Option<RegistrationInfo> {
self.read().await.values().find(|info| info.registration.as_token == token).cloned()
}
pub fn read(&self) -> impl Future<Output = tokio::sync::RwLockReadGuard<'_, BTreeMap<String, RegistrationInfo>>> {
self.registration_info.read()
}
}

View file

@ -55,10 +55,7 @@ impl Services<'_> {
db: &'static D, config: Config,
) -> Result<Self> {
Ok(Self {
appservice: appservice::Service {
db,
registration_info: RwLock::new(HashMap::new()),
},
appservice: appservice::Service::build(db)?,
pusher: pusher::Service {
db,
},

View file

@ -510,7 +510,7 @@ impl Service {
}
}
for appservice in services().appservice.registration_info.read().await.values() {
for appservice in services().appservice.read().await.values() {
if services().rooms.state_cache.appservice_in_room(&pdu.room_id, appservice)? {
services().sending.send_pdu_appservice(appservice.registration.id.clone(), pdu_id.clone())?;
continue;

View file

@ -502,7 +502,7 @@ impl Service {
let permit = services().sending.maximum_requests.acquire().await;
let response = match appservice_server::send_request(
services().appservice.get_registration(id).map_err(|e| (kind.clone(), e))?.ok_or_else(|| {
services().appservice.get_registration(id).await.ok_or_else(|| {
(
kind.clone(),
Error::bad_database("[Appservice] Could not load registration from db."),