Services refactor

Replace structs of Dep<Service> with OnceServices, so each service has a Services reference

Remove service name => Service map

Flatten Services.rooms

Make reqwest Clients lazy initialized (client service)
This commit is contained in:
dasha_uwu
2025-08-22 20:15:54 +05:00
parent 26b3a84b88
commit b5890b9664
118 changed files with 457 additions and 1923 deletions

View File

@@ -16,10 +16,8 @@ use tuwunel_core::{
};
use tuwunel_database::{Deserialized, Handle, Ignore, Json, Map};
use crate::{Dep, globals};
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
@@ -28,16 +26,10 @@ struct Data {
roomusertype_roomuserdataid: Arc<Map>,
}
struct Services {
globals: Dep<globals::Service>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
globals: args.depend::<globals::Service>("globals"),
},
services: args.services.clone(),
db: Data {
roomuserdataid_accountdata: args.db["roomuserdataid_accountdata"].clone(),
roomusertype_roomuserdataid: args.db["roomusertype_roomuserdataid"].clone(),

View File

@@ -12,11 +12,9 @@ use termimad::MadSkin;
use tokio::task::JoinHandle;
use tuwunel_core::{Server, debug, defer, error, log, log::is_systemd_mode};
use crate::{Dep, admin};
pub struct Console {
server: Arc<Server>,
admin: Dep<admin::Service>,
services: Arc<crate::services::OnceServices>,
worker_join: Mutex<Option<JoinHandle<()>>>,
input_abort: Mutex<Option<AbortHandle>>,
command_abort: Mutex<Option<AbortHandle>>,
@@ -31,7 +29,7 @@ impl Console {
pub(super) fn new(args: &crate::Args<'_>) -> Arc<Self> {
Arc::new(Self {
server: args.server.clone(),
admin: args.depend::<admin::Service>("admin"),
services: args.services.clone(),
worker_join: None.into(),
input_abort: None.into(),
command_abort: None.into(),
@@ -177,7 +175,12 @@ impl Console {
}
async fn process(self: Arc<Self>, line: String) {
match self.admin.command_in_place(line, None).await {
match self
.services
.admin
.command_in_place(line, None)
.await
{
| Ok(Some(ref content)) => self.output(content),
| Err(ref content) => self.output_err(content),
| _ => unreachable!(),
@@ -213,7 +216,8 @@ impl Console {
}
fn tab_complete(&self, line: &str) -> String {
self.admin
self.services
.admin
.complete_command(line)
.unwrap_or_else(|| line.to_owned())
}

View File

@@ -45,12 +45,11 @@ pub async fn create_admin_room(services: &Services) -> Result {
let room_version = RoomVersionId::V11;
let _short_id = services
.rooms
.short
.get_or_create_shortroomid(&room_id)
.await;
let state_lock = services.rooms.state.mutex.lock(&room_id).await;
let state_lock = services.state.mutex.lock(&room_id).await;
// Create a user for the server
let server_user = services.globals.server_user.as_ref();
@@ -69,7 +68,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
// 1. The room create event
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(String::new(), &RoomCreateEventContent {
@@ -87,7 +85,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
// 2. Make server user/bot join
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(
@@ -105,7 +102,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
let users = BTreeMap::from_iter([(server_user.into(), 69420.into())]);
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(String::new(), &RoomPowerLevelsEventContent {
@@ -121,7 +117,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
// 4.1 Join Rules
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(String::new(), &RoomJoinRulesEventContent::new(JoinRule::Invite)),
@@ -134,7 +129,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
// 4.2 History Visibility
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(
@@ -150,7 +144,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
// 4.3 Guest Access
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(
@@ -167,7 +160,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
// 5. Events implied by name and topic
let room_name = format!("{} Admin Room", services.config.server_name);
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(String::new(), &RoomNameEventContent::new(room_name)),
@@ -179,7 +171,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
.await?;
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(String::new(), &RoomTopicEventContent {
@@ -197,7 +188,6 @@ pub async fn create_admin_room(services: &Services) -> Result {
let alias = &services.globals.admin_alias;
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(String::new(), &RoomCanonicalAliasEventContent {
@@ -212,13 +202,11 @@ pub async fn create_admin_room(services: &Services) -> Result {
.await?;
services
.rooms
.alias
.set_alias(alias, &room_id, server_user)?;
// 7. (ad-hoc) Disable room URL previews for everyone by default
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder::state(String::new(), &RoomPreviewUrlsEventContent { disabled: true }),

View File

@@ -5,7 +5,7 @@ mod grant;
use std::{
pin::Pin,
sync::{Arc, RwLock as StdRwLock, Weak},
sync::{Arc, RwLock as StdRwLock},
};
use async_trait::async_trait;
@@ -17,13 +17,13 @@ use ruma::{
};
use tokio::sync::{RwLock, mpsc};
use tuwunel_core::{
Err, Error, Event, Result, Server, debug, err, error, error::default_log, pdu::PduBuilder,
Err, Error, Event, Result, debug, err, error, error::default_log, pdu::PduBuilder,
};
use crate::{Dep, account_data, globals, rooms, rooms::state::RoomMutexGuard};
use crate::rooms::state::RoomMutexGuard;
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
channel: StdRwLock<Option<mpsc::Sender<CommandInput>>>,
pub handle: RwLock<Option<Processor>>,
pub complete: StdRwLock<Option<Completer>>,
@@ -31,18 +31,6 @@ pub struct Service {
pub console: Arc<console::Console>,
}
struct Services {
server: Arc<Server>,
globals: Dep<globals::Service>,
alias: Dep<rooms::alias::Service>,
timeline: Dep<rooms::timeline::Service>,
state: Dep<rooms::state::Service>,
state_cache: Dep<rooms::state_cache::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
account_data: Dep<account_data::Service>,
services: StdRwLock<Option<Weak<crate::Services>>>,
}
/// Inputs to a command are a multi-line string and optional reply_id.
#[derive(Clone, Debug, Default)]
pub struct CommandInput {
@@ -77,18 +65,7 @@ const COMMAND_QUEUE_LIMIT: usize = 512;
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
server: args.server.clone(),
globals: args.depend::<globals::Service>("globals"),
alias: args.depend::<rooms::alias::Service>("rooms::alias"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
state: args.depend::<rooms::state::Service>("rooms::state"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
account_data: args.depend::<account_data::Service>("account_data"),
services: None.into(),
},
services: args.services.clone(),
channel: StdRwLock::new(None),
handle: RwLock::new(None),
complete: StdRwLock::new(None),
@@ -234,16 +211,7 @@ impl Service {
.await
.expect("Admin module is not loaded");
let services = self
.services
.services
.read()
.expect("locked")
.as_ref()
.and_then(Weak::upgrade)
.expect("Services self-reference not initialized.");
handle(services, command).await
handle(Arc::clone(self.services.get_services()), command).await
}
/// Checks whether a given user is an admin of this server
@@ -423,17 +391,4 @@ impl Service {
.await
.unwrap_or(false)
}
/// Sets the self-reference to crate::Services which will provide context to
/// the admin commands.
pub(super) fn set_services(&self, services: Option<&Arc<crate::Services>>) {
let receiver = &mut *self
.services
.services
.write()
.expect("locked for writing");
let weak = services.map(Arc::downgrade);
*receiver = weak;
}
}

View File

@@ -11,23 +11,17 @@ use async_trait::async_trait;
use futures::{Future, FutureExt, Stream, StreamExt, TryStreamExt};
use ruma::{RoomAliasId, RoomId, UserId, api::appservice::Registration};
use tokio::sync::{RwLock, RwLockReadGuard};
use tuwunel_core::{Err, Result, Server, debug, err, utils::stream::IterStream};
use tuwunel_core::{Err, Result, debug, err, utils::stream::IterStream};
use tuwunel_database::Map;
pub use self::{namespace_regex::NamespaceRegex, registration_info::RegistrationInfo};
use crate::{Dep, sending};
pub struct Service {
registration_info: RwLock<Registrations>,
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
struct Services {
sending: Dep<sending::Service>,
server: Arc<Server>,
}
struct Data {
id_appserviceregistrations: Arc<Map>,
}
@@ -39,10 +33,7 @@ impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
registration_info: RwLock::new(BTreeMap::new()),
services: Services {
sending: args.depend::<sending::Service>("sending"),
server: args.server.clone(),
},
services: args.services.clone(),
db: Data {
id_appserviceregistrations: args.db["id_appserviceregistrations"].clone(),
},

View File

@@ -1,22 +1,26 @@
use std::{sync::Arc, time::Duration};
use std::{
sync::{Arc, LazyLock},
time::Duration,
};
use either::Either;
use ipaddress::IPAddress;
use reqwest::redirect;
use tuwunel_core::{Config, Result, err, implement, trace};
use crate::{resolver, service};
use crate::{service, services::OnceServices};
type ClientLazylock = LazyLock<reqwest::Client, Box<dyn FnOnce() -> reqwest::Client + Send>>;
pub struct Service {
pub default: reqwest::Client,
pub url_preview: reqwest::Client,
pub extern_media: reqwest::Client,
pub well_known: reqwest::Client,
pub federation: reqwest::Client,
pub synapse: reqwest::Client,
pub sender: reqwest::Client,
pub appservice: reqwest::Client,
pub pusher: reqwest::Client,
pub default: ClientLazylock,
pub url_preview: ClientLazylock,
pub extern_media: ClientLazylock,
pub well_known: ClientLazylock,
pub federation: ClientLazylock,
pub synapse: ClientLazylock,
pub sender: ClientLazylock,
pub appservice: ClientLazylock,
pub pusher: ClientLazylock,
pub cidr_range_denylist: Vec<IPAddress>,
}
@@ -24,86 +28,89 @@ pub struct Service {
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
let config = &args.server.config;
let resolver = args.require::<resolver::Service>("resolver");
let url_preview_bind_addr = config
.url_preview_bound_interface
.clone()
.and_then(Either::left);
let url_preview_bind_iface = config
.url_preview_bound_interface
.clone()
.and_then(Either::right);
macro_rules! create_client {
($config:ident, $services:ident; $expr:expr) => {{
fn make($services: Arc<OnceServices>) -> Result<reqwest::Client> {
let $config = &$services.server.config;
Ok($expr.build()?)
}
let services = Arc::clone(args.services);
LazyLock::new(Box::new(|| make(services).unwrap()))
}};
}
Ok(Arc::new(Self {
default: base(config)?
.dns_resolver(resolver.resolver.clone())
.build()?,
default: create_client!(config, services; base(config)?
.dns_resolver(Arc::clone(&services.resolver.resolver))),
url_preview: base(config)
url_preview: create_client!(config, services; {
let url_preview_bind_addr = config
.url_preview_bound_interface
.clone()
.and_then(Either::left);
let url_preview_bind_iface = config
.url_preview_bound_interface
.clone()
.and_then(Either::right);
base(config)
.and_then(|builder| {
builder_interface(builder, url_preview_bind_iface.as_deref())
})?
.local_address(url_preview_bind_addr)
.dns_resolver(resolver.resolver.clone())
.dns_resolver(Arc::clone(&services.resolver.resolver))
.redirect(redirect::Policy::limited(3))
.build()?,
}),
extern_media: base(config)?
.dns_resolver(resolver.resolver.clone())
.redirect(redirect::Policy::limited(3))
.build()?,
extern_media: create_client!(config, services; base(config)?
.dns_resolver(Arc::clone(&services.resolver.resolver))
.redirect(redirect::Policy::limited(3))),
well_known: base(config)?
.dns_resolver(resolver.resolver.clone())
well_known: create_client!(config, services; base(config)?
.dns_resolver(Arc::clone(&services.resolver.resolver))
.connect_timeout(Duration::from_secs(config.well_known_conn_timeout))
.read_timeout(Duration::from_secs(config.well_known_timeout))
.timeout(Duration::from_secs(config.well_known_timeout))
.pool_max_idle_per_host(0)
.redirect(redirect::Policy::limited(4))
.build()?,
.redirect(redirect::Policy::limited(4))),
federation: base(config)?
.dns_resolver(resolver.resolver.hooked.clone())
federation: create_client!(config, services; base(config)?
.dns_resolver(Arc::clone(&services.resolver.resolver.hooked))
.read_timeout(Duration::from_secs(config.federation_timeout))
.pool_max_idle_per_host(config.federation_idle_per_host.into())
.pool_idle_timeout(Duration::from_secs(config.federation_idle_timeout))
.redirect(redirect::Policy::limited(3))
.build()?,
.redirect(redirect::Policy::limited(3))),
synapse: base(config)?
.dns_resolver(resolver.resolver.hooked.clone())
synapse: create_client!(config, services; base(config)?
.dns_resolver(Arc::clone(&services.resolver.resolver.hooked))
.read_timeout(Duration::from_secs(305))
.pool_max_idle_per_host(0)
.redirect(redirect::Policy::limited(3))
.build()?,
.redirect(redirect::Policy::limited(3))),
sender: base(config)?
.dns_resolver(resolver.resolver.hooked.clone())
sender: create_client!(config, services; base(config)?
.dns_resolver(Arc::clone(&services.resolver.resolver.hooked))
.read_timeout(Duration::from_secs(config.sender_timeout))
.timeout(Duration::from_secs(config.sender_timeout))
.pool_max_idle_per_host(1)
.pool_idle_timeout(Duration::from_secs(config.sender_idle_timeout))
.redirect(redirect::Policy::limited(2))
.build()?,
.redirect(redirect::Policy::limited(2))),
appservice: base(config)?
.dns_resolver(resolver.resolver.clone())
appservice: create_client!(config, services; base(config)?
.dns_resolver(Arc::clone(&services.resolver.resolver))
.connect_timeout(Duration::from_secs(5))
.read_timeout(Duration::from_secs(config.appservice_timeout))
.timeout(Duration::from_secs(config.appservice_timeout))
.pool_max_idle_per_host(1)
.pool_idle_timeout(Duration::from_secs(config.appservice_idle_timeout))
.redirect(redirect::Policy::limited(2))
.build()?,
.redirect(redirect::Policy::limited(2))),
pusher: base(config)?
.dns_resolver(resolver.resolver.clone())
pusher: create_client!(config, services; base(config)?
.dns_resolver(Arc::clone(&services.resolver.resolver))
.pool_max_idle_per_host(1)
.pool_idle_timeout(Duration::from_secs(config.pusher_idle_timeout))
.redirect(redirect::Policy::limited(2))
.build()?,
.redirect(redirect::Policy::limited(2))),
cidr_range_denylist: config
.ip_range_denylist

View File

@@ -9,31 +9,14 @@ use ruma::{
};
use tuwunel_core::{Result, debug_warn, error, warn};
use crate::{Dep, account_data, config, globals, users};
pub struct Service {
services: Services,
}
struct Services {
account_data: Dep<account_data::Service>,
config: Dep<config::Service>,
globals: Dep<globals::Service>,
users: Dep<users::Service>,
services: Arc<crate::services::OnceServices>,
}
#[async_trait]
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
account_data: args.depend::<account_data::Service>("account_data"),
config: args.depend::<config::Service>("config"),
globals: args.depend::<globals::Service>("globals"),
users: args.depend::<users::Service>("users"),
},
}))
Ok(Arc::new(Self { services: args.services.clone() }))
}
async fn worker(self: Arc<Self>) -> Result {

View File

@@ -2,31 +2,17 @@ mod execute;
use std::sync::Arc;
use tuwunel_core::{Result, Server};
use tuwunel_core::Result;
use crate::{Dep, client, resolver, server_keys};
use crate::services::OnceServices;
pub struct Service {
services: Services,
}
struct Services {
server: Arc<Server>,
client: Dep<client::Service>,
resolver: Dep<resolver::Service>,
server_keys: Dep<server_keys::Service>,
services: Arc<OnceServices>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
server: args.server.clone(),
client: args.depend::<client::Service>("client"),
resolver: args.depend::<resolver::Service>("resolver"),
server_keys: args.depend::<server_keys::Service>("server_keys"),
},
}))
Ok(Arc::new(Self { services: args.services.clone() }))
}
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }

View File

@@ -12,11 +12,9 @@ use tuwunel_core::{
};
use tuwunel_database::{Deserialized, Ignore, Interfix, Json, Map};
use crate::{Dep, globals};
pub struct Service {
db: Data,
services: Services,
services: Arc<crate::services::OnceServices>,
}
struct Data {
@@ -25,10 +23,6 @@ struct Data {
backupkeyid_backup: Arc<Map>,
}
struct Services {
globals: Dep<globals::Service>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
@@ -37,9 +31,7 @@ impl crate::Service for Service {
backupid_etag: args.db["backupid_etag"].clone(),
backupkeyid_backup: args.db["backupkeyid_backup"].clone(),
},
services: Services {
globals: args.depend::<globals::Service>("globals"),
},
services: args.services.clone(),
}))
}

View File

@@ -10,13 +10,13 @@ use tuwunel_core::{
Err, Error, Result, Server, debug, debug_warn, error, trace, utils::time, warn,
};
use crate::{Services, service, service::Service};
use crate::{Services, service::Service};
pub(crate) struct Manager {
manager: Mutex<Option<JoinHandle<Result>>>,
workers: Mutex<Workers>,
server: Arc<Server>,
service: Arc<service::Map>,
services: Arc<Services>,
}
type Workers = JoinSet<WorkerResult>;
@@ -26,12 +26,12 @@ type WorkersLocked<'a> = MutexGuard<'a, Workers>;
const RESTART_DELAY_MS: u64 = 2500;
impl Manager {
pub(super) fn new(services: &Services) -> Arc<Self> {
pub(super) fn new(services: &Arc<Services>) -> Arc<Self> {
Arc::new(Self {
manager: Mutex::new(None),
workers: Mutex::new(JoinSet::new()),
server: services.server.clone(),
service: services.service.clone(),
services: services.clone(),
})
}
@@ -55,19 +55,8 @@ impl Manager {
.spawn(async move { self_.worker().await }),
);
// we can't hold the lock during the iteration with start_worker so the values
// are snapshotted here
let services: Vec<Arc<dyn Service>> = self
.service
.read()
.expect("locked for reading")
.values()
.map(|val| val.0.upgrade())
.map(|arc| arc.expect("services available for manager startup"))
.collect();
debug!("Starting service workers...");
for service in services {
for service in self.services.services() {
self.start_worker(&mut workers, &service).await?;
}

View File

@@ -15,14 +15,13 @@ use tokio::{
io::{AsyncReadExt, AsyncWriteExt, BufReader},
};
use tuwunel_core::{
Err, Result, Server, debug, debug_error, debug_info, debug_warn, err, error, trace,
Err, Result, debug, debug_error, debug_info, debug_warn, err, error, trace,
utils::{self, MutexMap},
warn,
};
use self::data::{Data, Metadata};
pub use self::thumbnail::Dim;
use crate::{Dep, client, globals, sending};
#[derive(Debug)]
pub struct FileMeta {
@@ -34,14 +33,7 @@ pub struct FileMeta {
pub struct Service {
url_preview_mutex: MutexMap<String, ()>,
pub(super) db: Data,
services: Services,
}
struct Services {
server: Arc<Server>,
client: Dep<client::Service>,
globals: Dep<globals::Service>,
sending: Dep<sending::Service>,
services: Arc<crate::services::OnceServices>,
}
/// generated MXC ID (`media-id`) length
@@ -59,12 +51,7 @@ impl crate::Service for Service {
Ok(Arc::new(Self {
url_preview_mutex: MutexMap::new(),
db: Data::new(args.db),
services: Services {
server: args.server.clone(),
client: args.depend::<client::Service>("client"),
globals: args.depend::<globals::Service>("globals"),
sending: args.depend::<sending::Service>("sending"),
},
services: args.services.clone(),
}))
}

View File

@@ -186,7 +186,6 @@ async fn migrate(services: &Services) -> Result {
let patterns = services.globals.forbidden_alias_names();
if !patterns.is_empty() {
for room_id in services
.rooms
.metadata
.iter_ids()
.map(ToOwned::to_owned)
@@ -194,7 +193,6 @@ async fn migrate(services: &Services) -> Result {
.await
{
services
.rooms
.alias
.local_aliases_for_room(&room_id)
.ready_for_each(|room_alias| {
@@ -406,7 +404,6 @@ async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services)
let _cork = db.cork_and_sync();
let room_ids = services
.rooms
.metadata
.iter_ids()
.map(ToOwned::to_owned)
@@ -417,7 +414,6 @@ async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services)
debug_info!("Fixing room {room_id}");
let users_in_room: Vec<OwnedUserId> = services
.rooms
.state_cache
.room_members(room_id)
.map(ToOwned::to_owned)
@@ -429,7 +425,6 @@ async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services)
.stream()
.filter(|user_id| {
services
.rooms
.state_accessor
.get_member(room_id, user_id)
.map(|member| {
@@ -444,7 +439,6 @@ async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services)
.stream()
.filter(|user_id| {
services
.rooms
.state_accessor
.get_member(room_id, user_id)
.map(|member| {
@@ -457,7 +451,6 @@ async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services)
for user_id in &joined_members {
debug_info!("User is joined, marking as joined");
services
.rooms
.state_cache
.mark_as_joined(user_id, room_id);
}
@@ -465,7 +458,6 @@ async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services)
for user_id in &non_joined_members {
debug_info!("User is left or banned, marking as left");
services
.rooms
.state_cache
.mark_as_left(user_id, room_id);
}
@@ -478,7 +470,6 @@ async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services)
);
services
.rooms
.state_cache
.update_joined_count(room_id)
.await;

View File

@@ -27,7 +27,7 @@ pub mod transaction_ids;
pub mod uiaa;
pub mod users;
pub(crate) use service::{Args, Dep, Service};
pub(crate) use service::{Args, Service};
pub use crate::services::Services;

View File

@@ -9,17 +9,11 @@ use tuwunel_core::{
use tuwunel_database::{Deserialized, Json, Map};
use super::Presence;
use crate::{Dep, globals, users};
pub(crate) struct Data {
presenceid_presence: Arc<Map>,
userid_presenceid: Arc<Map>,
services: Services,
}
struct Services {
globals: Dep<globals::Service>,
users: Dep<users::Service>,
services: Arc<crate::services::OnceServices>,
}
impl Data {
@@ -28,10 +22,7 @@ impl Data {
Self {
presenceid_presence: db["presenceid_presence"].clone(),
userid_presenceid: db["userid_presenceid"].clone(),
services: Services {
globals: args.depend::<globals::Service>("globals"),
users: args.depend::<users::Service>("users"),
},
services: args.services.clone(),
}
}

View File

@@ -8,13 +8,9 @@ use futures::{Stream, StreamExt, TryFutureExt, stream::FuturesUnordered};
use loole::{Receiver, Sender};
use ruma::{OwnedUserId, UInt, UserId, events::presence::PresenceEvent, presence::PresenceState};
use tokio::time::sleep;
use tuwunel_core::{
Error, Result, Server, checked, debug, debug_warn, error, result::LogErr, trace,
};
use tuwunel_database::Database;
use tuwunel_core::{Error, Result, checked, debug, debug_warn, error, result::LogErr, trace};
use self::{data::Data, presence::Presence};
use crate::{Dep, globals, users};
pub struct Service {
timer_channel: (Sender<TimerType>, Receiver<TimerType>),
@@ -22,14 +18,7 @@ pub struct Service {
idle_timeout: u64,
offline_timeout: u64,
db: Data,
services: Services,
}
struct Services {
server: Arc<Server>,
db: Arc<Database>,
globals: Dep<globals::Service>,
users: Dep<users::Service>,
services: Arc<crate::services::OnceServices>,
}
type TimerType = (OwnedUserId, Duration);
@@ -46,12 +35,7 @@ impl crate::Service for Service {
idle_timeout: checked!(idle_timeout_s * 1_000)?,
offline_timeout: checked!(offline_timeout_s * 1_000)?,
db: Data::new(&args),
services: Services {
server: args.server.clone(),
db: args.db.clone(),
globals: args.depend::<globals::Service>("globals"),
users: args.depend::<users::Service>("users"),
},
services: args.services.clone(),
}))
}

View File

@@ -29,20 +29,9 @@ use tuwunel_core::{
};
use tuwunel_database::{Deserialized, Ignore, Interfix, Json, Map};
use crate::{Dep, client, globals, rooms, sending, users};
pub struct Service {
db: Data,
services: Services,
}
struct Services {
globals: Dep<globals::Service>,
client: Dep<client::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
state_cache: Dep<rooms::state_cache::Service>,
users: Dep<users::Service>,
sending: Dep<sending::Service>,
services: Arc<crate::services::OnceServices>,
}
struct Data {
@@ -57,15 +46,7 @@ impl crate::Service for Service {
senderkey_pusher: args.db["senderkey_pusher"].clone(),
pushkey_deviceid: args.db["pushkey_deviceid"].clone(),
},
services: Services {
globals: args.depend::<globals::Service>("globals"),
client: args.depend::<client::Service>("client"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
users: args.depend::<users::Service>("users"),
sending: args.depend::<sending::Service>("sending"),
},
services: args.services.clone(),
}))
}

View File

@@ -9,21 +9,15 @@ mod well_known;
use std::sync::Arc;
use async_trait::async_trait;
use tuwunel_core::{Result, Server, arrayvec::ArrayString, utils::MutexMap};
use tuwunel_core::{Result, arrayvec::ArrayString, utils::MutexMap};
use self::{cache::Cache, dns::Resolver};
use crate::{Dep, client};
pub struct Service {
pub cache: Arc<Cache>,
pub resolver: Arc<Resolver>,
resolving: Resolving,
services: Services,
}
struct Services {
server: Arc<Server>,
client: Dep<client::Service>,
services: Arc<crate::services::OnceServices>,
}
type Resolving = MutexMap<NameBuf, ()>;
@@ -42,10 +36,7 @@ impl crate::Service for Service {
cache: cache.clone(),
resolver: Resolver::build(args.server, cache)?,
resolving: MutexMap::new(),
services: Services {
server: args.server.clone(),
client: args.depend::<client::Service>("client"),
},
services: args.services.clone(),
}))
}

View File

@@ -8,17 +8,17 @@ use ruma::{
events::StateEventType,
};
use tuwunel_core::{
Err, Result, Server, err,
Err, Result, err,
matrix::Event,
utils::{ReadyExt, stream::TryIgnore},
};
use tuwunel_database::{Deserialized, Ignore, Interfix, Map};
use crate::{Dep, admin, appservice, appservice::RegistrationInfo, globals, rooms, sending};
use crate::appservice::RegistrationInfo;
pub struct Service {
db: Data,
services: Services,
services: Arc<crate::services::OnceServices>,
}
struct Data {
@@ -27,15 +27,6 @@ struct Data {
aliasid_alias: Arc<Map>,
}
struct Services {
server: Arc<Server>,
admin: Dep<admin::Service>,
appservice: Dep<appservice::Service>,
globals: Dep<globals::Service>,
sending: Dep<sending::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
@@ -44,15 +35,7 @@ impl crate::Service for Service {
alias_roomid: args.db["alias_roomid"].clone(),
aliasid_alias: args.db["aliasid_alias"].clone(),
},
services: Services {
server: args.server.clone(),
admin: args.depend::<admin::Service>("admin"),
appservice: args.depend::<appservice::Service>("appservice"),
globals: args.depend::<globals::Service>("globals"),
sending: args.depend::<sending::Service>("sending"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
},
services: args.services.clone(),
}))
}

View File

@@ -21,29 +21,19 @@ use tuwunel_core::{
};
use self::data::Data;
use crate::{Dep, rooms, rooms::short::ShortEventId};
use crate::rooms::short::ShortEventId;
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
struct Services {
short: Dep<rooms::short::Service>,
state: Dep<rooms::state::Service>,
timeline: Dep<rooms::timeline::Service>,
}
type Bucket<'a> = BTreeSet<(u64, &'a EventId)>;
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
short: args.depend::<rooms::short::Service>("rooms::short"),
state: args.depend::<rooms::state::Service>("rooms::state"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
},
services: args.services.clone(),
db: Data::new(&args),
}))
}

View File

@@ -21,31 +21,14 @@ use std::{
use async_trait::async_trait;
use ruma::{EventId, OwnedRoomId, RoomId};
use tuwunel_core::{
Err, Result, Server, implement,
Err, Result, implement,
matrix::{Event, PduEvent},
utils::{MutexMap, continue_exponential_backoff},
};
use crate::{Dep, globals, rooms, sending, server_keys};
pub struct Service {
pub mutex_federation: RoomMutexMap,
services: Services,
}
struct Services {
globals: Dep<globals::Service>,
sending: Dep<sending::Service>,
auth_chain: Dep<rooms::auth_chain::Service>,
metadata: Dep<rooms::metadata::Service>,
pdu_metadata: Dep<rooms::pdu_metadata::Service>,
server_keys: Dep<server_keys::Service>,
short: Dep<rooms::short::Service>,
state: Dep<rooms::state::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
state_compressor: Dep<rooms::state_compressor::Service>,
timeline: Dep<rooms::timeline::Service>,
server: Arc<Server>,
services: Arc<crate::services::OnceServices>,
}
type RoomMutexMap = MutexMap<OwnedRoomId, ()>;
@@ -55,22 +38,7 @@ impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
mutex_federation: RoomMutexMap::new(),
services: Services {
globals: args.depend::<globals::Service>("globals"),
sending: args.depend::<sending::Service>("sending"),
auth_chain: args.depend::<rooms::auth_chain::Service>("rooms::auth_chain"),
metadata: args.depend::<rooms::metadata::Service>("rooms::metadata"),
server_keys: args.depend::<server_keys::Service>("server_keys"),
pdu_metadata: args.depend::<rooms::pdu_metadata::Service>("rooms::pdu_metadata"),
short: args.depend::<rooms::short::Service>("rooms::short"),
state: args.depend::<rooms::state::Service>("rooms::state"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
state_compressor: args
.depend::<rooms::state_compressor::Service>("rooms::state_compressor"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
server: args.server.clone(),
},
services: args.services.clone(),
}))
}

View File

@@ -11,11 +11,9 @@ use tuwunel_core::{
};
use tuwunel_database::Map;
use crate::{Dep, rooms};
pub struct Service {
db: Data,
services: Services,
services: Arc<crate::services::OnceServices>,
}
struct Data {
@@ -25,12 +23,6 @@ struct Data {
pduid_pdu: Arc<Map>,
}
struct Services {
directory: Dep<rooms::directory::Service>,
short: Dep<rooms::short::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
@@ -40,12 +32,7 @@ impl crate::Service for Service {
roomid_shortroomid: args.db["roomid_shortroomid"].clone(),
pduid_pdu: args.db["pduid_pdu"].clone(),
},
services: Services {
directory: args.depend::<rooms::directory::Service>("rooms::directory"),
short: args.depend::<rooms::short::Service>("rooms::short"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
},
services: args.services.clone(),
}))
}

View File

@@ -17,27 +17,3 @@ pub mod threads;
pub mod timeline;
pub mod typing;
pub mod user;
use std::sync::Arc;
pub struct Service {
pub alias: Arc<alias::Service>,
pub auth_chain: Arc<auth_chain::Service>,
pub directory: Arc<directory::Service>,
pub event_handler: Arc<event_handler::Service>,
pub lazy_loading: Arc<lazy_loading::Service>,
pub metadata: Arc<metadata::Service>,
pub pdu_metadata: Arc<pdu_metadata::Service>,
pub read_receipt: Arc<read_receipt::Service>,
pub search: Arc<search::Service>,
pub short: Arc<short::Service>,
pub spaces: Arc<spaces::Service>,
pub state: Arc<state::Service>,
pub state_accessor: Arc<state_accessor::Service>,
pub state_cache: Arc<state_cache::Service>,
pub state_compressor: Arc<state_compressor::Service>,
pub threads: Arc<threads::Service>,
pub timeline: Arc<timeline::Service>,
pub typing: Arc<typing::Service>,
pub user: Arc<user::Service>,
}

View File

@@ -14,23 +14,16 @@ use tuwunel_core::{
};
use tuwunel_database::Map;
use crate::{
Dep, rooms,
rooms::{
short::{ShortEventId, ShortRoomId},
timeline::{PduId, RawPduId},
},
use crate::rooms::{
short::{ShortEventId, ShortRoomId},
timeline::{PduId, RawPduId},
};
pub(super) struct Data {
tofrom_relation: Arc<Map>,
referencedevents: Arc<Map>,
softfailedeventids: Arc<Map>,
services: Services,
}
struct Services {
timeline: Dep<rooms::timeline::Service>,
services: Arc<crate::services::OnceServices>,
}
impl Data {
@@ -40,9 +33,7 @@ impl Data {
tofrom_relation: db["tofrom_relation"].clone(),
referencedevents: db["referencedevents"].clone(),
softfailedeventids: db["softfailedeventids"].clone(),
services: Services {
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
},
services: args.services.clone(),
}
}

View File

@@ -9,25 +9,16 @@ use tuwunel_core::{
};
use self::data::Data;
use crate::{Dep, rooms};
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
struct Services {
short: Dep<rooms::short::Service>,
timeline: Dep<rooms::timeline::Service>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
short: args.depend::<rooms::short::Service>("rooms::short"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
},
services: args.services.clone(),
db: Data::new(&args),
}))
}

View File

@@ -12,19 +12,13 @@ use tuwunel_core::{
};
use tuwunel_database::{Deserialized, Json, Map};
use crate::{Dep, globals};
pub(super) struct Data {
roomuserid_privateread: Arc<Map>,
roomuserid_lastprivatereadupdate: Arc<Map>,
services: Services,
services: Arc<crate::services::OnceServices>,
readreceiptid_readreceipt: Arc<Map>,
}
struct Services {
globals: Dep<globals::Service>,
}
pub(super) type ReceiptItem<'a> = (&'a UserId, u64, Raw<AnySyncEphemeralRoomEvent>);
impl Data {
@@ -34,9 +28,7 @@ impl Data {
roomuserid_privateread: db["roomuserid_privateread"].clone(),
roomuserid_lastprivatereadupdate: db["roomuserid_lastprivatereadupdate"].clone(),
readreceiptid_readreceipt: db["readreceiptid_readreceipt"].clone(),
services: Services {
globals: args.depend::<globals::Service>("globals"),
},
services: args.services.clone(),
}
}

View File

@@ -21,27 +21,16 @@ use tuwunel_core::{
};
use self::data::{Data, ReceiptItem};
use crate::{Dep, rooms, sending};
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
struct Services {
sending: Dep<sending::Service>,
short: Dep<rooms::short::Service>,
timeline: Dep<rooms::timeline::Service>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
sending: args.depend::<sending::Service>("sending"),
short: args.depend::<rooms::short::Service>("rooms::short"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
},
services: args.services.clone(),
db: Data::new(&args),
}))
}

View File

@@ -14,29 +14,20 @@ use tuwunel_core::{
};
use tuwunel_database::{Map, keyval::Val};
use crate::{
Dep, rooms,
rooms::{
short::ShortRoomId,
timeline::{PduId, RawPduId},
},
use crate::rooms::{
short::ShortRoomId,
timeline::{PduId, RawPduId},
};
pub struct Service {
db: Data,
services: Services,
services: Arc<crate::services::OnceServices>,
}
struct Data {
tokenids: Arc<Map>,
}
struct Services {
short: Dep<rooms::short::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
timeline: Dep<rooms::timeline::Service>,
}
#[derive(Clone, Debug)]
pub struct RoomQuery<'a> {
pub room_id: &'a RoomId,
@@ -56,12 +47,7 @@ impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
db: Data { tokenids: args.db["tokenids"].clone() },
services: Services {
short: args.depend::<rooms::short::Service>("rooms::short"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
},
services: args.services.clone(),
}))
}

View File

@@ -7,11 +7,9 @@ pub use tuwunel_core::matrix::pdu::{ShortEventId, ShortId, ShortRoomId, ShortSta
use tuwunel_core::{Result, err, implement, matrix::StateKey, utils, utils::IterStream};
use tuwunel_database::{Deserialized, Get, Map, Qry};
use crate::{Dep, globals};
pub struct Service {
db: Data,
services: Services,
services: Arc<crate::services::OnceServices>,
}
struct Data {
@@ -23,10 +21,6 @@ struct Data {
statehash_shortstatehash: Arc<Map>,
}
struct Services {
globals: Dep<globals::Service>,
}
pub type ShortStateHash = ShortId;
impl crate::Service for Service {
@@ -40,9 +34,7 @@ impl crate::Service for Service {
roomid_shortroomid: args.db["roomid_shortroomid"].clone(),
statehash_shortstatehash: args.db["statehash_shortstatehash"].clone(),
},
services: Services {
globals: args.depend::<globals::Service>("globals"),
},
services: args.services.clone(),
}))
}

View File

@@ -32,22 +32,12 @@ use tuwunel_core::{
};
pub use self::pagination_token::PaginationToken;
use crate::{Dep, rooms, sending};
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
pub roomid_spacehierarchy_cache: Mutex<Cache>,
}
struct Services {
state_accessor: Dep<rooms::state_accessor::Service>,
state_cache: Dep<rooms::state_cache::Service>,
state: Dep<rooms::state::Service>,
event_handler: Dep<rooms::event_handler::Service>,
timeline: Dep<rooms::timeline::Service>,
sending: Dep<sending::Service>,
}
pub struct CachedSpaceHierarchySummary {
summary: SpaceHierarchyParentSummary,
}
@@ -74,16 +64,7 @@ impl crate::Service for Service {
let cache_size = f64::from(config.roomid_spacehierarchy_cache_capacity);
let cache_size = cache_size * config.cache_capacity_modifier;
Ok(Arc::new(Self {
services: Services {
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
state: args.depend::<rooms::state::Service>("rooms::state"),
event_handler: args
.depend::<rooms::event_handler::Service>("rooms::event_handler"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
sending: args.depend::<sending::Service>("sending"),
},
services: args.services.clone(),
roomid_spacehierarchy_cache: Mutex::new(LruCache::new(usize_from_f64(cache_size)?)),
}))
}

View File

@@ -25,29 +25,19 @@ use tuwunel_core::{
use tuwunel_database::{Deserialized, Ignore, Interfix, Map};
use crate::{
Dep, globals, rooms,
rooms::{
short::{ShortEventId, ShortStateHash, ShortStateKey},
state_compressor::{CompressedState, parse_compressed_state_event},
},
services::OnceServices,
};
pub struct Service {
pub mutex: RoomMutexMap,
services: Services,
services: Arc<OnceServices>,
db: Data,
}
struct Services {
globals: Dep<globals::Service>,
short: Dep<rooms::short::Service>,
spaces: Dep<rooms::spaces::Service>,
state_cache: Dep<rooms::state_cache::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
state_compressor: Dep<rooms::state_compressor::Service>,
timeline: Dep<rooms::timeline::Service>,
}
struct Data {
shorteventid_shortstatehash: Arc<Map>,
roomid_shortstatehash: Arc<Map>,
@@ -62,17 +52,7 @@ impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
mutex: RoomMutexMap::new(),
services: Services {
globals: args.depend::<globals::Service>("globals"),
short: args.depend::<rooms::short::Service>("rooms::short"),
spaces: args.depend::<rooms::spaces::Service>("rooms::spaces"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
state_compressor: args
.depend::<rooms::state_compressor::Service>("rooms::state_compressor"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
},
services: args.services.clone(),
db: Data {
shorteventid_shortstatehash: args.db["shorteventid_shortstatehash"].clone(),
roomid_shortstatehash: args.db["roomid_shortstatehash"].clone(),

View File

@@ -33,21 +33,11 @@ use tuwunel_core::{
};
use tuwunel_database::Map;
use crate::{Dep, rooms};
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
struct Services {
short: Dep<rooms::short::Service>,
state: Dep<rooms::state::Service>,
state_compressor: Dep<rooms::state_compressor::Service>,
state_cache: Dep<rooms::state_cache::Service>,
timeline: Dep<rooms::timeline::Service>,
}
struct Data {
shorteventid_shortstatehash: Arc<Map>,
}
@@ -56,14 +46,7 @@ struct Data {
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
short: args.depend::<rooms::short::Service>("rooms::short"),
state: args.depend::<rooms::state::Service>("rooms::state"),
state_compressor: args
.depend::<rooms::state_compressor::Service>("rooms::state_compressor"),
},
services: args.services.clone(),
db: Data {
shorteventid_shortstatehash: args.db["shorteventid_shortstatehash"].clone(),
},

View File

@@ -20,23 +20,14 @@ use tuwunel_core::{
};
use tuwunel_database::{Deserialized, Ignore, Interfix, Map};
use crate::{Dep, account_data, appservice::RegistrationInfo, config, globals, rooms, users};
use crate::appservice::RegistrationInfo;
pub struct Service {
appservice_in_room_cache: AppServiceInRoomCache,
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
struct Services {
account_data: Dep<account_data::Service>,
config: Dep<config::Service>,
globals: Dep<globals::Service>,
metadata: Dep<rooms::metadata::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
users: Dep<users::Service>,
}
struct Data {
roomid_knockedcount: Arc<Map>,
roomid_invitedcount: Arc<Map>,
@@ -63,15 +54,7 @@ impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
appservice_in_room_cache: RwLock::new(HashMap::new()),
services: Services {
account_data: args.depend::<account_data::Service>("account_data"),
config: args.depend::<config::Service>("config"),
globals: args.depend::<globals::Service>("globals"),
metadata: args.depend::<rooms::metadata::Service>("rooms::metadata"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
users: args.depend::<users::Service>("users"),
},
services: args.services.clone(),
db: Data {
roomid_knockedcount: args.db["roomid_knockedcount"].clone(),
roomid_invitedcount: args.db["roomid_invitedcount"].clone(),

View File

@@ -17,20 +17,12 @@ use tuwunel_core::{
};
use tuwunel_database::Map;
use crate::{
Dep, rooms,
rooms::short::{ShortEventId, ShortId, ShortStateHash, ShortStateKey},
};
use crate::rooms::short::{ShortEventId, ShortId, ShortStateHash, ShortStateKey};
pub struct Service {
pub stateinfo_cache: Mutex<StateInfoLruCache>,
db: Data,
services: Services,
}
struct Services {
short: Dep<rooms::short::Service>,
state: Dep<rooms::state::Service>,
services: Arc<crate::services::OnceServices>,
}
struct Data {
@@ -77,10 +69,7 @@ impl crate::Service for Service {
db: Data {
shortstatehash_statediff: args.db["shortstatehash_statediff"].clone(),
},
services: Services {
short: args.depend::<rooms::short::Service>("rooms::short"),
state: args.depend::<rooms::state::Service>("rooms::state"),
},
services: args.services.clone(),
}))
}

View File

@@ -16,16 +16,9 @@ use tuwunel_core::{
};
use tuwunel_database::{Deserialized, Map};
use crate::{Dep, rooms};
pub struct Service {
db: Data,
services: Services,
}
struct Services {
short: Dep<rooms::short::Service>,
timeline: Dep<rooms::timeline::Service>,
services: Arc<crate::services::OnceServices>,
}
pub(super) struct Data {
@@ -38,10 +31,7 @@ impl crate::Service for Service {
db: Data {
threadid_userids: args.db["threadid_userids"].clone(),
},
services: Services {
short: args.depend::<rooms::short::Service>("rooms::short"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
},
services: args.services.clone(),
}))
}

View File

@@ -22,7 +22,7 @@ use ruma::{
use serde::Deserialize;
pub use tuwunel_core::matrix::pdu::{PduId, RawPduId};
use tuwunel_core::{
Err, Result, Server, at, err, implement,
Err, Result, at, err, implement,
matrix::pdu::{PduCount, PduEvent},
utils::{
MutexMap, MutexMapGuard,
@@ -33,41 +33,14 @@ use tuwunel_core::{
};
use tuwunel_database::{Database, Deserialized, Json, KeyVal, Map};
use crate::{
Dep, account_data, admin, appservice, globals, pusher, rooms, rooms::short::ShortRoomId,
sending, server_keys, users,
};
use crate::rooms::short::ShortRoomId;
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
pub mutex_insert: RoomMutexMap,
}
struct Services {
server: Arc<Server>,
account_data: Dep<account_data::Service>,
appservice: Dep<appservice::Service>,
admin: Dep<admin::Service>,
alias: Dep<rooms::alias::Service>,
globals: Dep<globals::Service>,
short: Dep<rooms::short::Service>,
state: Dep<rooms::state::Service>,
state_cache: Dep<rooms::state_cache::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
pdu_metadata: Dep<rooms::pdu_metadata::Service>,
read_receipt: Dep<rooms::read_receipt::Service>,
sending: Dep<sending::Service>,
server_keys: Dep<server_keys::Service>,
user: Dep<rooms::user::Service>,
users: Dep<users::Service>,
pusher: Dep<pusher::Service>,
threads: Dep<rooms::threads::Service>,
search: Dep<rooms::search::Service>,
spaces: Dep<rooms::spaces::Service>,
event_handler: Dep<rooms::event_handler::Service>,
}
struct Data {
eventid_outlierpdu: Arc<Map>,
eventid_pduid: Arc<Map>,
@@ -107,31 +80,7 @@ pub type PdusIterItem = (PduCount, PduEvent);
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
server: args.server.clone(),
account_data: args.depend::<account_data::Service>("account_data"),
appservice: args.depend::<appservice::Service>("appservice"),
admin: args.depend::<admin::Service>("admin"),
alias: args.depend::<rooms::alias::Service>("rooms::alias"),
globals: args.depend::<globals::Service>("globals"),
short: args.depend::<rooms::short::Service>("rooms::short"),
state: args.depend::<rooms::state::Service>("rooms::state"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
pdu_metadata: args.depend::<rooms::pdu_metadata::Service>("rooms::pdu_metadata"),
read_receipt: args.depend::<rooms::read_receipt::Service>("rooms::read_receipt"),
sending: args.depend::<sending::Service>("sending"),
server_keys: args.depend::<server_keys::Service>("server_keys"),
user: args.depend::<rooms::user::Service>("rooms::user"),
users: args.depend::<users::Service>("users"),
pusher: args.depend::<pusher::Service>("pusher"),
threads: args.depend::<rooms::threads::Service>("rooms::threads"),
search: args.depend::<rooms::search::Service>("rooms::search"),
spaces: args.depend::<rooms::spaces::Service>("rooms::spaces"),
event_handler: args
.depend::<rooms::event_handler::Service>("rooms::event_handler"),
},
services: args.services.clone(),
db: Data {
eventid_outlierpdu: args.db["eventid_outlierpdu"].clone(),
eventid_pduid: args.db["eventid_pduid"].clone(),

View File

@@ -11,11 +11,11 @@ use tuwunel_core::{
utils::{self, IterStream},
};
use crate::{Dep, globals, sending, sending::EduBuf, users};
use crate::sending::EduBuf;
pub struct Service {
server: Arc<Server>,
services: Services,
services: Arc<crate::services::OnceServices>,
/// u64 is unix timestamp of timeout
pub typing: RwLock<BTreeMap<OwnedRoomId, BTreeMap<OwnedUserId, u64>>>,
/// timestamp of the last change to typing users
@@ -23,21 +23,11 @@ pub struct Service {
pub typing_update_sender: broadcast::Sender<OwnedRoomId>,
}
struct Services {
globals: Dep<globals::Service>,
sending: Dep<sending::Service>,
users: Dep<users::Service>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
server: args.server.clone(),
services: Services {
globals: args.depend::<globals::Service>("globals"),
sending: args.depend::<sending::Service>("sending"),
users: args.depend::<users::Service>("users"),
},
services: args.services.clone(),
typing: RwLock::new(BTreeMap::new()),
last_typing_update: RwLock::new(BTreeMap::new()),
typing_update_sender: broadcast::channel(100).0,

View File

@@ -4,11 +4,11 @@ use ruma::{RoomId, UserId};
use tuwunel_core::{Result, implement};
use tuwunel_database::{Database, Deserialized, Map};
use crate::{Dep, globals, rooms, rooms::short::ShortStateHash};
use crate::rooms::short::ShortStateHash;
pub struct Service {
db: Data,
services: Services,
services: Arc<crate::services::OnceServices>,
}
struct Data {
@@ -19,11 +19,6 @@ struct Data {
roomsynctoken_shortstatehash: Arc<Map>,
}
struct Services {
globals: Dep<globals::Service>,
short: Dep<rooms::short::Service>,
}
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
@@ -34,11 +29,7 @@ impl crate::Service for Service {
roomuserid_lastnotificationread: args.db["userroomid_highlightcount"].clone(),
roomsynctoken_shortstatehash: args.db["roomsynctoken_shortstatehash"].clone(),
},
services: Services {
globals: args.depend::<globals::Service>("globals"),
short: args.depend::<rooms::short::Service>("rooms::short"),
},
services: args.services.clone(),
}))
}

View File

@@ -9,7 +9,6 @@ use tuwunel_core::{
use tuwunel_database::{Database, Deserialized, Map};
use super::{Destination, SendingEvent};
use crate::{Dep, globals};
pub(super) type OutgoingItem = (Key, SendingEvent, Destination);
pub(super) type SendingItem = (Key, SendingEvent);
@@ -21,11 +20,7 @@ pub struct Data {
servernameevent_data: Arc<Map>,
servername_educount: Arc<Map>,
pub(super) db: Arc<Database>,
services: Services,
}
struct Services {
globals: Dep<globals::Service>,
services: Arc<crate::services::OnceServices>,
}
impl Data {
@@ -36,9 +31,7 @@ impl Data {
servernameevent_data: db["servernameevent_data"].clone(),
servername_educount: db["servername_educount"].clone(),
db: args.db.clone(),
services: Services {
globals: args.depend::<globals::Service>("globals"),
},
services: args.services.clone(),
}
}

View File

@@ -29,34 +29,15 @@ pub use self::{
dest::Destination,
sender::{EDU_LIMIT, PDU_LIMIT},
};
use crate::{
Dep, account_data, client, federation, globals, presence, pusher, rooms,
rooms::timeline::RawPduId, users,
};
use crate::rooms::timeline::RawPduId;
pub struct Service {
pub db: Data,
server: Arc<Server>,
services: Services,
services: Arc<crate::services::OnceServices>,
channels: Vec<(loole::Sender<Msg>, loole::Receiver<Msg>)>,
}
struct Services {
client: Dep<client::Service>,
globals: Dep<globals::Service>,
state: Dep<rooms::state::Service>,
state_cache: Dep<rooms::state_cache::Service>,
user: Dep<rooms::user::Service>,
users: Dep<users::Service>,
presence: Dep<presence::Service>,
read_receipt: Dep<rooms::read_receipt::Service>,
timeline: Dep<rooms::timeline::Service>,
account_data: Dep<account_data::Service>,
appservice: Dep<crate::appservice::Service>,
pusher: Dep<pusher::Service>,
federation: Dep<federation::Service>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
struct Msg {
dest: Destination,
@@ -85,21 +66,7 @@ impl crate::Service for Service {
Ok(Arc::new(Self {
db: Data::new(&args),
server: args.server.clone(),
services: Services {
client: args.depend::<client::Service>("client"),
globals: args.depend::<globals::Service>("globals"),
state: args.depend::<rooms::state::Service>("rooms::state"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
user: args.depend::<rooms::user::Service>("rooms::user"),
users: args.depend::<users::Service>("users"),
presence: args.depend::<presence::Service>("presence"),
read_receipt: args.depend::<rooms::read_receipt::Service>("rooms::read_receipt"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
account_data: args.depend::<account_data::Service>("account_data"),
appservice: args.depend::<crate::appservice::Service>("appservice"),
pusher: args.depend::<pusher::Service>("pusher"),
federation: args.depend::<federation::Service>("federation"),
},
services: args.services.clone(),
channels: (0..num_senders)
.map(|_| loole::unbounded())
.collect(),

View File

@@ -18,27 +18,19 @@ use ruma::{
};
use serde_json::value::RawValue as RawJsonValue;
use tuwunel_core::{
Result, Server, implement,
Result, implement,
utils::{IterStream, timepoint_from_now},
};
use tuwunel_database::{Deserialized, Json, Map};
use crate::{Dep, globals, sending};
pub struct Service {
keypair: Box<Ed25519KeyPair>,
verify_keys: VerifyKeys,
minimum_valid: Duration,
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
struct Services {
globals: Dep<globals::Service>,
sending: Dep<sending::Service>,
server: Arc<Server>,
}
struct Data {
server_signingkeys: Arc<Map>,
}
@@ -58,11 +50,7 @@ impl crate::Service for Service {
keypair,
verify_keys,
minimum_valid,
services: Services {
globals: args.depend::<globals::Service>("globals"),
sending: args.depend::<sending::Service>("sending"),
server: args.server.clone(),
},
services: args.services.clone(),
db: Data {
server_signingkeys: args.db["server_signingkeys"].clone(),
},

View File

@@ -1,17 +1,11 @@
use std::{
any::Any,
collections::BTreeMap,
fmt::Write,
ops::Deref,
sync::{Arc, OnceLock, RwLock, Weak},
};
use std::{any::Any, fmt::Write, sync::Arc};
use async_trait::async_trait;
use tuwunel_core::{
Err, Result, Server, err, error::inspect_log, utils::string::SplitInfallible,
};
use tuwunel_core::{Result, Server, utils::string::SplitInfallible};
use tuwunel_database::Database;
use crate::services::OnceServices;
/// Abstract interface for a Service
#[async_trait]
pub(crate) trait Service: Any + Send + Sync {
@@ -53,130 +47,7 @@ pub(crate) trait Service: Any + Send + Sync {
pub(crate) struct Args<'a> {
pub(crate) server: &'a Arc<Server>,
pub(crate) db: &'a Arc<Database>,
pub(crate) service: &'a Arc<Map>,
}
/// Dep is a reference to a service used within another service.
/// Circular-dependencies between services require this indirection.
pub(crate) struct Dep<T: Service + Send + Sync> {
dep: OnceLock<Arc<T>>,
service: Weak<Map>,
name: &'static str,
}
pub(crate) type Map = RwLock<MapType>;
pub(crate) type MapType = BTreeMap<MapKey, MapVal>;
pub(crate) type MapVal = (Weak<dyn Service>, Weak<dyn Any + Send + Sync>);
pub(crate) type MapKey = String;
/// SAFETY: Workaround for a compiler limitation (or bug) where it is Hard to
/// prove the Sync'ness of Dep because services contain circular references
/// to other services through Dep's. The Sync'ness of Dep can still be
/// proved without unsafety by declaring the crate-attribute #![recursion_limit
/// = "192"] but this may take a while. Re-evaluate this when a new trait-solver
/// (such as Chalk) becomes available.
unsafe impl<T: Service> Sync for Dep<T> {}
/// SAFETY: Ancillary to unsafe impl Sync; while this is not needed to prevent
/// violating the recursion_limit, the trait-solver still spends an inordinate
/// amount of time to prove this.
unsafe impl<T: Service> Send for Dep<T> {}
impl<T: Service + Send + Sync> Deref for Dep<T> {
type Target = Arc<T>;
/// Dereference a dependency. The dependency must be ready or panics.
#[inline]
fn deref(&self) -> &Self::Target {
self.dep.get_or_init(
#[inline(never)]
|| self.init(),
)
}
}
impl<T: Service + Send + Sync> Dep<T> {
#[inline]
fn init(&self) -> Arc<T> {
let service = self
.service
.upgrade()
.expect("services map exists for dependency initialization.");
require::<T>(&service, self.name)
}
}
impl<'a> Args<'a> {
/// Create a lazy-reference to a service when constructing another Service.
#[inline]
pub(crate) fn depend<T: Service>(&'a self, name: &'static str) -> Dep<T> {
Dep::<T> {
dep: OnceLock::new(),
service: Arc::downgrade(self.service),
name,
}
}
/// Create a reference immediately to a service when constructing another
/// Service. The other service must be constructed.
#[inline]
pub(crate) fn require<T: Service>(&'a self, name: &str) -> Arc<T> {
require::<T>(self.service, name)
}
}
/// Reference a Service by name. Panics if the Service does not exist or was
/// incorrectly cast.
#[inline]
fn require<T: Service>(map: &Map, name: &str) -> Arc<T> {
try_get::<T>(map, name)
.inspect_err(inspect_log)
.expect("Failure to reference service required by another service.")
}
/// Reference a Service by name. Returns None if the Service does not exist, but
/// panics if incorrectly cast.
///
/// # Panics
/// Incorrect type is not a silent failure (None) as the type never has a reason
/// to be incorrect.
pub(crate) fn get<T>(map: &Map, name: &str) -> Option<Arc<T>>
where
T: Any + Send + Sync + Sized,
{
map.read()
.expect("locked for reading")
.get(name)
.map(|(_, s)| {
s.upgrade().map(|s| {
s.downcast::<T>()
.expect("Service must be correctly downcast.")
})
})?
}
/// Reference a Service by name. Returns Err if the Service does not exist or
/// was incorrectly cast.
pub(crate) fn try_get<T>(map: &Map, name: &str) -> Result<Arc<T>>
where
T: Any + Send + Sync + Sized,
{
map.read()
.expect("locked for reading")
.get(name)
.map_or_else(
|| Err!("Service {name:?} does not exist or has not been built yet."),
|(_, s)| {
s.upgrade().map_or_else(
|| Err!("Service {name:?} no longer exists."),
|s| {
s.downcast::<T>()
.map_err(|_| err!("Service {name:?} must be correctly downcast."))
},
)
},
)
pub(crate) services: &'a Arc<OnceServices>,
}
/// Utility for service implementations; see Service::name() in the trait.

View File

@@ -1,19 +1,18 @@
use std::{
any::Any,
collections::BTreeMap,
sync::{Arc, RwLock},
ops::Deref,
sync::{Arc, OnceLock},
};
use futures::{Stream, StreamExt, TryStreamExt};
use futures::{StreamExt, TryStreamExt};
use tokio::sync::Mutex;
use tuwunel_core::{Result, Server, debug, debug_info, info, trace, utils::stream::IterStream};
use tuwunel_core::{Result, Server, debug, debug_info, err, info, trace};
use tuwunel_database::Database;
use crate::{
account_data, admin, appservice, client, config, emergency, federation, globals, key_backups,
manager::Manager,
media, presence, pusher, resolver, rooms, sending, server_keys, service,
service::{Args, Map, Service},
media, presence, pusher, resolver, rooms, sending, server_keys,
service::{Args, Service},
sync, transaction_ids, uiaa, users,
};
@@ -30,7 +29,25 @@ pub struct Services {
pub presence: Arc<presence::Service>,
pub pusher: Arc<pusher::Service>,
pub resolver: Arc<resolver::Service>,
pub rooms: rooms::Service,
pub alias: Arc<rooms::alias::Service>,
pub auth_chain: Arc<rooms::auth_chain::Service>,
pub directory: Arc<rooms::directory::Service>,
pub event_handler: Arc<rooms::event_handler::Service>,
pub lazy_loading: Arc<rooms::lazy_loading::Service>,
pub metadata: Arc<rooms::metadata::Service>,
pub pdu_metadata: Arc<rooms::pdu_metadata::Service>,
pub read_receipt: Arc<rooms::read_receipt::Service>,
pub search: Arc<rooms::search::Service>,
pub short: Arc<rooms::short::Service>,
pub spaces: Arc<rooms::spaces::Service>,
pub state: Arc<rooms::state::Service>,
pub state_accessor: Arc<rooms::state_accessor::Service>,
pub state_cache: Arc<rooms::state_cache::Service>,
pub state_compressor: Arc<rooms::state_compressor::Service>,
pub threads: Arc<rooms::threads::Service>,
pub timeline: Arc<rooms::timeline::Service>,
pub typing: Arc<rooms::typing::Service>,
pub user: Arc<rooms::user::Service>,
pub federation: Arc<federation::Service>,
pub sending: Arc<sending::Service>,
pub server_keys: Arc<server_keys::Service>,
@@ -40,29 +57,44 @@ pub struct Services {
pub users: Arc<users::Service>,
manager: Mutex<Option<Arc<Manager>>>,
pub(crate) service: Arc<Map>,
pub server: Arc<Server>,
pub db: Arc<Database>,
}
pub struct OnceServices {
lock: OnceLock<Arc<Services>>,
}
impl OnceServices {
pub fn get_services(&self) -> &Arc<Services> {
self.lock
.get()
.expect("services must be initialized")
}
}
impl Deref for OnceServices {
type Target = Arc<Services>;
fn deref(&self) -> &Self::Target { self.get_services() }
}
impl Services {
#[allow(clippy::cognitive_complexity)]
pub async fn build(server: Arc<Server>) -> Result<Arc<Self>> {
let db = Database::open(&server).await?;
let service: Arc<Map> = Arc::new(RwLock::new(BTreeMap::new()));
let services = Arc::new(OnceServices { lock: OnceLock::new() });
macro_rules! build {
($tyname:ty) => {{
let built = <$tyname>::build(Args {
($tyname:ty) => {
<$tyname>::build(Args {
db: &db,
server: &server,
service: &service,
})?;
add_service(&service, built.clone(), built.clone());
built
}};
services: &services,
})?
};
}
Ok(Arc::new(Self {
let res = Arc::new(Self {
account_data: build!(account_data::Service),
admin: build!(admin::Service),
appservice: build!(appservice::Service),
@@ -75,27 +107,25 @@ impl Services {
media: build!(media::Service),
presence: build!(presence::Service),
pusher: build!(pusher::Service),
rooms: rooms::Service {
alias: build!(rooms::alias::Service),
auth_chain: build!(rooms::auth_chain::Service),
directory: build!(rooms::directory::Service),
event_handler: build!(rooms::event_handler::Service),
lazy_loading: build!(rooms::lazy_loading::Service),
metadata: build!(rooms::metadata::Service),
pdu_metadata: build!(rooms::pdu_metadata::Service),
read_receipt: build!(rooms::read_receipt::Service),
search: build!(rooms::search::Service),
short: build!(rooms::short::Service),
spaces: build!(rooms::spaces::Service),
state: build!(rooms::state::Service),
state_accessor: build!(rooms::state_accessor::Service),
state_cache: build!(rooms::state_cache::Service),
state_compressor: build!(rooms::state_compressor::Service),
threads: build!(rooms::threads::Service),
timeline: build!(rooms::timeline::Service),
typing: build!(rooms::typing::Service),
user: build!(rooms::user::Service),
},
alias: build!(rooms::alias::Service),
auth_chain: build!(rooms::auth_chain::Service),
directory: build!(rooms::directory::Service),
event_handler: build!(rooms::event_handler::Service),
lazy_loading: build!(rooms::lazy_loading::Service),
metadata: build!(rooms::metadata::Service),
pdu_metadata: build!(rooms::pdu_metadata::Service),
read_receipt: build!(rooms::read_receipt::Service),
search: build!(rooms::search::Service),
short: build!(rooms::short::Service),
spaces: build!(rooms::spaces::Service),
state: build!(rooms::state::Service),
state_accessor: build!(rooms::state_accessor::Service),
state_cache: build!(rooms::state_cache::Service),
state_compressor: build!(rooms::state_compressor::Service),
threads: build!(rooms::threads::Service),
timeline: build!(rooms::timeline::Service),
typing: build!(rooms::typing::Service),
user: build!(rooms::user::Service),
federation: build!(federation::Service),
sending: build!(sending::Service),
server_keys: build!(server_keys::Service),
@@ -105,18 +135,22 @@ impl Services {
users: build!(users::Service),
manager: Mutex::new(None),
service,
server,
db,
}))
});
services
.lock
.set(res.clone())
.map_err(|_| err!("couldn't set services lock"))
.unwrap();
Ok(res)
}
pub async fn start(self: &Arc<Self>) -> Result<Arc<Self>> {
debug_info!("Starting services...");
self.admin
.set_services(Some(Arc::clone(self)).as_ref());
super::migrations::migrations(self).await?;
self.manager
.lock()
@@ -157,8 +191,6 @@ impl Services {
manager.stop().await;
}
self.admin.set_services(None);
debug_info!("Services shutdown complete.");
}
@@ -170,8 +202,51 @@ impl Services {
Ok(())
}
pub(crate) fn services(&self) -> [Arc<dyn Service>; 38] {
[
self.account_data.clone(),
self.admin.clone(),
self.appservice.clone(),
self.resolver.clone(),
self.client.clone(),
self.config.clone(),
self.emergency.clone(),
self.globals.clone(),
self.key_backups.clone(),
self.media.clone(),
self.presence.clone(),
self.pusher.clone(),
self.alias.clone(),
self.auth_chain.clone(),
self.directory.clone(),
self.event_handler.clone(),
self.lazy_loading.clone(),
self.metadata.clone(),
self.pdu_metadata.clone(),
self.read_receipt.clone(),
self.search.clone(),
self.short.clone(),
self.spaces.clone(),
self.state.clone(),
self.state_accessor.clone(),
self.state_cache.clone(),
self.state_compressor.clone(),
self.threads.clone(),
self.timeline.clone(),
self.typing.clone(),
self.user.clone(),
self.federation.clone(),
self.sending.clone(),
self.server_keys.clone(),
self.sync.clone(),
self.transaction_ids.clone(),
self.uiaa.clone(),
self.users.clone(),
]
}
pub async fn clear_cache(&self) {
self.services()
futures::stream::iter(self.services())
.for_each(async |service| {
service.clear_cache().await;
})
@@ -179,7 +254,7 @@ impl Services {
}
pub async fn memory_usage(&self) -> Result<String> {
self.services()
futures::stream::iter(self.services())
.map(Ok)
.try_fold(String::new(), async |mut out, service| {
service.memory_usage(&mut out).await?;
@@ -190,55 +265,10 @@ impl Services {
fn interrupt(&self) {
debug!("Interrupting services...");
for (name, (service, ..)) in self
.service
.read()
.expect("locked for reading")
.iter()
{
if let Some(service) = service.upgrade() {
trace!("Interrupting {name}");
service.interrupt();
}
for service in self.services() {
let name = service.name();
trace!("Interrupting {name}");
service.interrupt();
}
}
/// Iterate from snapshot of the services map
fn services(&self) -> impl Stream<Item = Arc<dyn Service>> + Send {
self.service
.read()
.expect("locked for reading")
.values()
.filter_map(|val| val.0.upgrade())
.collect::<Vec<_>>()
.into_iter()
.stream()
}
#[inline]
pub fn try_get<T>(&self, name: &str) -> Result<Arc<T>>
where
T: Any + Send + Sync + Sized,
{
service::try_get::<T>(&self.service, name)
}
#[inline]
pub fn get<T>(&self, name: &str) -> Option<Arc<T>>
where
T: Any + Send + Sync + Sized,
{
service::get::<T>(&self.service, name)
}
}
#[allow(clippy::needless_pass_by_value)]
fn add_service(map: &Arc<Map>, s: Arc<dyn Service>, a: Arc<dyn Any + Send + Sync>) {
let name = s.name();
let len = map.read().expect("locked for reading").len();
trace!("built service #{len}: {name:?}");
map.write()
.expect("locked for writing")
.insert(name.to_owned(), (Arc::downgrade(&s), Arc::downgrade(&a)));
}

View File

@@ -6,14 +6,12 @@ use std::{
};
use ruma::{OwnedDeviceId, OwnedRoomId, OwnedUserId, api::client::sync::sync_events::v5};
use tuwunel_core::{Result, Server};
use tuwunel_core::Result;
use tuwunel_database::Map;
use crate::{Dep, rooms};
pub struct Service {
db: Data,
services: Services,
services: Arc<crate::services::OnceServices>,
snake_connections: DbConnections<SnakeConnectionsKey, SnakeConnectionsVal>,
}
@@ -33,13 +31,6 @@ pub struct Data {
userid_lastonetimekeyupdate: Arc<Map>,
}
struct Services {
server: Arc<Server>,
short: Dep<rooms::short::Service>,
state_cache: Dep<rooms::state_cache::Service>,
typing: Dep<rooms::typing::Service>,
}
#[derive(Default)]
struct SnakeSyncCache {
lists: BTreeMap<String, v5::request::List>,
@@ -70,12 +61,7 @@ impl crate::Service for Service {
readreceiptid_readreceipt: args.db["readreceiptid_readreceipt"].clone(),
userid_lastonetimekeyupdate: args.db["userid_lastonetimekeyupdate"].clone(),
},
services: Services {
server: args.server.clone(),
short: args.depend::<rooms::short::Service>("rooms::short"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
typing: args.depend::<rooms::typing::Service>("rooms::typing"),
},
services: args.services.clone(),
snake_connections: StdMutex::new(BTreeMap::new()),
}))
}

View File

@@ -16,18 +16,10 @@ use tuwunel_core::{
};
use tuwunel_database::{Deserialized, Json, Map};
use crate::{Dep, config, globals, users};
pub struct Service {
userdevicesessionid_uiaarequest: RwLock<RequestMap>,
db: Data,
services: Services,
}
struct Services {
globals: Dep<globals::Service>,
users: Dep<users::Service>,
config: Dep<config::Service>,
services: Arc<crate::services::OnceServices>,
}
struct Data {
@@ -46,11 +38,7 @@ impl crate::Service for Service {
db: Data {
userdevicesessionid_uiaainfo: args.db["userdevicesessionid_uiaainfo"].clone(),
},
services: Services {
globals: args.depend::<globals::Service>("globals"),
users: args.depend::<users::Service>("users"),
config: args.depend::<config::Service>("config"),
},
services: args.services.clone(),
}))
}

View File

@@ -343,15 +343,15 @@ pub async fn mark_device_key_update(&self, user_id: &UserId) {
let count = self.services.globals.next_count();
self.services
.state_cache
.rooms_joined(user_id)
// Don't send key updates to unencrypted rooms
.filter(|room_id| self.services.state_accessor.is_encrypted_room(room_id))
.ready_for_each(|room_id| {
let key = (room_id, *count);
self.db.keychangeid_userid.put_raw(key, user_id);
})
.await;
.state_cache
.rooms_joined(user_id)
// Don't send key updates to unencrypted rooms
.filter(|room_id| self.services.state_accessor.is_encrypted_room(room_id))
.ready_for_each(|room_id| {
let key = (room_id, *count);
self.db.keychangeid_userid.put_raw(key, user_id);
})
.await;
let key = (user_id, *count);
self.db.keychangeid_userid.put_raw(key, user_id);

View File

@@ -12,28 +12,18 @@ use ruma::{
events::{GlobalAccountDataEventType, ignored_user_list::IgnoredUserListEvent},
};
use tuwunel_core::{
Err, Result, Server, debug_warn, err, is_equal_to, trace,
Err, Result, debug_warn, err, is_equal_to, trace,
utils::{self, ReadyExt, stream::TryIgnore},
};
use tuwunel_database::{Deserialized, Json, Map};
pub use self::keys::parse_master_key;
use crate::{Dep, account_data, admin, globals, rooms};
pub struct Service {
services: Services,
services: Arc<crate::services::OnceServices>,
db: Data,
}
struct Services {
server: Arc<Server>,
account_data: Dep<account_data::Service>,
admin: Dep<admin::Service>,
globals: Dep<globals::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
state_cache: Dep<rooms::state_cache::Service>,
}
struct Data {
keychangeid_userid: Arc<Map>,
keyid_key: Arc<Map>,
@@ -62,15 +52,7 @@ struct Data {
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
Ok(Arc::new(Self {
services: Services {
server: args.server.clone(),
account_data: args.depend::<account_data::Service>("account_data"),
admin: args.depend::<admin::Service>("admin"),
globals: args.depend::<globals::Service>("globals"),
state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
},
services: args.services.clone(),
db: Data {
keychangeid_userid: args.db["keychangeid_userid"].clone(),
keyid_key: args.db["keyid_key"].clone(),