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

@@ -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;
}
}