Simplify default Result generics.

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk
2025-07-08 12:08:13 +00:00
parent 8244d78cb2
commit ae707ab465
42 changed files with 95 additions and 115 deletions

View File

@@ -58,7 +58,7 @@ pub async fn update(
user_id: &UserId,
event_type: RoomAccountDataEventType,
data: &serde_json::Value,
) -> Result<()> {
) -> Result {
if data.get("type").is_none() || data.get("content").is_none() {
return Err!(Request(InvalidParam("Account data doesn't have all required fields.")));
}

View File

@@ -275,7 +275,7 @@ impl Service {
.ok_or_else(|| err!(Request(NotFound("Admin user not joined to admin room"))))
}
async fn handle_response(&self, content: RoomMessageEventContent) -> Result<()> {
async fn handle_response(&self, content: RoomMessageEventContent) -> Result {
let Some(Relation::Reply { in_reply_to }) = content.relates_to.as_ref() else {
return Ok(());
};
@@ -309,7 +309,7 @@ impl Service {
content: RoomMessageEventContent,
room_id: &RoomId,
user_id: &UserId,
) -> Result<()> {
) -> Result {
assert!(self.user_is_admin(user_id).await, "sender is not admin");
let state_lock = self.services.state.mutex.lock(room_id).await;
@@ -334,7 +334,7 @@ impl Service {
room_id: &RoomId,
user_id: &UserId,
state_lock: &RoomMutexGuard,
) -> Result<()> {
) -> Result {
error!("Failed to build and append admin room response PDU: \"{e}\"");
let content = RoomMessageEventContent::text_plain(format!(
"Failed to build and append admin room PDU: \"{e}\"\n\nThe original admin command \

View File

@@ -119,7 +119,7 @@ fn prepare(&self, dest: &ServerName, mut request: http::Request<Vec<u8>>) -> Res
}
#[implement(super::Service)]
fn validate_url(&self, url: &Url) -> Result<()> {
fn validate_url(&self, url: &Url) -> Result {
if let Some(url_host) = url.host_str() {
if let Ok(ip) = IPAddress::parse(url_host) {
trace!("Checking request URL IP {ip:?}");

View File

@@ -163,7 +163,7 @@ pub async fn add_key(
room_id: &RoomId,
session_id: &str,
key_data: &Raw<KeyBackupData>,
) -> Result<()> {
) -> Result {
let key = (user_id, version);
if self
.db

View File

@@ -13,14 +13,14 @@ use tuwunel_core::{
use crate::{Services, service, service::Service};
pub(crate) struct Manager {
manager: Mutex<Option<JoinHandle<Result<()>>>>,
manager: Mutex<Option<JoinHandle<Result>>>,
workers: Mutex<Workers>,
server: Arc<Server>,
service: Arc<service::Map>,
}
type Workers = JoinSet<WorkerResult>;
type WorkerResult = (Arc<dyn Service>, Result<()>);
type WorkerResult = (Arc<dyn Service>, Result);
type WorkersLocked<'a> = MutexGuard<'a, Workers>;
const RESTART_DELAY_MS: u64 = 2500;
@@ -35,7 +35,7 @@ impl Manager {
})
}
pub(super) async fn poll(&self) -> Result<()> {
pub(super) async fn poll(&self) -> Result {
if let Some(manager) = &mut *self.manager.lock().await {
trace!("Polling service manager...");
return manager.await?;
@@ -44,7 +44,7 @@ impl Manager {
Ok(())
}
pub(super) async fn start(self: Arc<Self>) -> Result<()> {
pub(super) async fn start(self: Arc<Self>) -> Result {
let mut workers = self.workers.lock().await;
debug!("Starting service manager...");
@@ -83,7 +83,7 @@ impl Manager {
}
}
async fn worker(&self) -> Result<()> {
async fn worker(&self) -> Result {
loop {
let mut workers = self.workers.lock().await;
tokio::select! {
@@ -99,7 +99,7 @@ impl Manager {
Ok(())
}
async fn handle_abort(&self, _workers: &mut WorkersLocked<'_>, error: Error) -> Result<()> {
async fn handle_abort(&self, _workers: &mut WorkersLocked<'_>, error: Error) -> Result {
// not supported until service can be associated with abort
unimplemented!("unexpected worker task abort {error:?}");
}
@@ -108,7 +108,7 @@ impl Manager {
&self,
workers: &mut WorkersLocked<'_>,
result: WorkerResult,
) -> Result<()> {
) -> Result {
let (service, result) = result;
match result {
| Ok(()) => self.handle_finished(workers, &service).await,
@@ -120,7 +120,7 @@ impl Manager {
&self,
_workers: &mut WorkersLocked<'_>,
service: &Arc<dyn Service>,
) -> Result<()> {
) -> Result {
debug!("service {:?} worker finished", service.name());
Ok(())
}
@@ -130,7 +130,7 @@ impl Manager {
workers: &mut WorkersLocked<'_>,
service: &Arc<dyn Service>,
error: Error,
) -> Result<()> {
) -> Result {
let name = service.name();
error!("service {name:?} aborted: {error}");
@@ -155,7 +155,7 @@ impl Manager {
&self,
workers: &mut WorkersLocked<'_>,
service: &Arc<dyn Service>,
) -> Result<()> {
) -> Result {
if !self.server.running() {
return Err!(
"Service {:?} worker not starting during server shutdown.",

View File

@@ -165,7 +165,7 @@ impl Data {
}
#[inline]
pub(super) fn remove_url_preview(&self, url: &str) -> Result<()> {
pub(super) fn remove_url_preview(&self, url: &str) -> Result {
self.url_previews.remove(url.as_bytes());
Ok(())
}
@@ -175,7 +175,7 @@ impl Data {
url: &str,
data: &UrlPreviewData,
timestamp: Duration,
) -> Result<()> {
) -> Result {
let mut value = Vec::<u8>::new();
value.extend_from_slice(&timestamp.as_secs().to_be_bytes());
value.push(0xFF);

View File

@@ -18,7 +18,7 @@ use crate::Services;
/// Migrates a media directory from legacy base64 file names to sha2 file names.
/// All errors are fatal. Upon success the database is keyed to not perform this
/// again.
pub(crate) async fn migrate_sha256_media(services: &Services) -> Result<()> {
pub(crate) async fn migrate_sha256_media(services: &Services) -> Result {
let db = &services.db;
let config = &services.server.config;
@@ -57,7 +57,7 @@ pub(crate) async fn migrate_sha256_media(services: &Services) -> Result<()> {
/// - Going back and forth to non-sha256 legacy binaries (e.g. upstream).
/// - Deletion of artifacts in the media directory which will then fall out of
/// sync with the database.
pub(crate) async fn checkup_sha256_media(services: &Services) -> Result<()> {
pub(crate) async fn checkup_sha256_media(services: &Services) -> Result {
use crate::media::encode_key;
debug!("Checking integrity of media directory");
@@ -101,7 +101,7 @@ async fn handle_media_check(
key: &[u8],
new_path: &OsStr,
old_path: &OsStr,
) -> Result<()> {
) -> Result {
use crate::media::encode_key;
let (mediaid_file, mediaid_user) = dbs;

View File

@@ -68,7 +68,7 @@ impl crate::Service for Service {
}))
}
async fn worker(self: Arc<Self>) -> Result<()> {
async fn worker(self: Arc<Self>) -> Result {
self.create_media_dir().await?;
Ok(())
@@ -86,7 +86,7 @@ impl Service {
content_disposition: Option<&ContentDisposition>,
content_type: Option<&str>,
file: &[u8],
) -> Result<()> {
) -> Result {
// Width, Height = 0 if it's not a thumbnail
let key = self.db.create_file_metadata(
mxc,
@@ -104,7 +104,7 @@ impl Service {
}
/// Deletes a file in the database and from the media directory via an MXC
pub async fn delete(&self, mxc: &Mxc<'_>) -> Result<()> {
pub async fn delete(&self, mxc: &Mxc<'_>) -> Result {
match self.db.search_mxc_metadata_prefix(mxc).await {
| Ok(keys) => {
for key in keys {
@@ -341,12 +341,12 @@ impl Service {
Ok(deletion_count)
}
pub async fn create_media_dir(&self) -> Result<()> {
pub async fn create_media_dir(&self) -> Result {
let dir = self.get_media_dir();
Ok(fs::create_dir_all(dir).await?)
}
async fn remove_media_file(&self, key: &[u8]) -> Result<()> {
async fn remove_media_file(&self, key: &[u8]) -> Result {
let path = self.get_media_file(key);
let legacy = self.get_media_file_b64(key);
debug!(?key, ?path, ?legacy, "Removing media file");

View File

@@ -49,13 +49,13 @@ pub struct UrlPreviewData {
}
#[implement(Service)]
pub async fn remove_url_preview(&self, url: &str) -> Result<()> {
pub async fn remove_url_preview(&self, url: &str) -> Result {
// TODO: also remove the downloaded image
self.db.remove_url_preview(url)
}
#[implement(Service)]
pub async fn set_url_preview(&self, url: &str, data: &UrlPreviewData) -> Result<()> {
pub async fn set_url_preview(&self, url: &str, data: &UrlPreviewData) -> Result {
let now = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("valid system time");

View File

@@ -439,7 +439,7 @@ pub async fn fetch_remote_content_legacy(
}
#[implement(super::Service)]
fn check_fetch_authorized(&self, mxc: &Mxc<'_>) -> Result<()> {
fn check_fetch_authorized(&self, mxc: &Mxc<'_>) -> Result {
if self
.services
.server
@@ -463,7 +463,7 @@ fn check_fetch_authorized(&self, mxc: &Mxc<'_>) -> Result<()> {
}
#[implement(super::Service)]
fn check_legacy_freeze(&self) -> Result<()> {
fn check_legacy_freeze(&self) -> Result {
self.services
.server
.config

View File

@@ -44,7 +44,7 @@ async fn long_file_names_works() {
Ok(key)
}
fn delete_file_mxc(&self, _mxc: String) -> Result<()> { todo!() }
fn delete_file_mxc(&self, _mxc: String) -> Result { todo!() }
fn search_mxc_metadata_prefix(&self, _mxc: String) -> Result<Vec<Vec<u8>>> { todo!() }
@@ -59,14 +59,14 @@ async fn long_file_names_works() {
todo!()
}
fn remove_url_preview(&self, _url: &str) -> Result<()> { todo!() }
fn remove_url_preview(&self, _url: &str) -> Result { todo!() }
fn set_url_preview(
&self,
_url: &str,
_data: &UrlPreviewData,
_timestamp: std::time::Duration,
) -> Result<()> {
) -> Result {
todo!()
}

View File

@@ -35,7 +35,7 @@ impl super::Service {
content_type: Option<&str>,
dim: &Dim,
file: &[u8],
) -> Result<()> {
) -> Result {
let key =
self.db
.create_file_metadata(mxc, user, dim, content_disposition, content_type)?;

View File

@@ -29,7 +29,7 @@ use crate::{Services, media};
/// equal or lesser version. These are expected to be backward-compatible.
pub(crate) const DATABASE_VERSION: u64 = 17;
pub(crate) async fn migrations(services: &Services) -> Result<()> {
pub(crate) async fn migrations(services: &Services) -> Result {
let users_count = services.users.count().await;
// Matrix resource ownership is based on the server name; changing it
@@ -52,7 +52,7 @@ pub(crate) async fn migrations(services: &Services) -> Result<()> {
}
}
async fn fresh(services: &Services) -> Result<()> {
async fn fresh(services: &Services) -> Result {
let db = &services.db;
services
@@ -77,7 +77,7 @@ async fn fresh(services: &Services) -> Result<()> {
}
/// Apply any migrations
async fn migrate(services: &Services) -> Result<()> {
async fn migrate(services: &Services) -> Result {
let db = &services.db;
let config = &services.server.config;
@@ -220,7 +220,7 @@ async fn migrate(services: &Services) -> Result<()> {
Ok(())
}
async fn db_lt_12(services: &Services) -> Result<()> {
async fn db_lt_12(services: &Services) -> Result {
for username in &services
.users
.list_local_users()
@@ -306,7 +306,7 @@ async fn db_lt_12(services: &Services) -> Result<()> {
Ok(())
}
async fn db_lt_13(services: &Services) -> Result<()> {
async fn db_lt_13(services: &Services) -> Result {
for username in &services
.users
.list_local_users()
@@ -353,7 +353,7 @@ async fn db_lt_13(services: &Services) -> Result<()> {
Ok(())
}
async fn fix_bad_double_separator_in_state_cache(services: &Services) -> Result<()> {
async fn fix_bad_double_separator_in_state_cache(services: &Services) -> Result {
warn!("Fixing bad double separator in state_cache roomuserid_joined");
let db = &services.db;
@@ -397,7 +397,7 @@ async fn fix_bad_double_separator_in_state_cache(services: &Services) -> Result<
Ok(())
}
async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services) -> Result<()> {
async fn retroactively_fix_bad_data_from_roomuserid_joined(services: &Services) -> Result {
warn!("Retroactively fixing bad data from broken roomuserid_joined");
let db = &services.db;

View File

@@ -58,7 +58,7 @@ impl Data {
currently_active: Option<bool>,
last_active_ago: Option<UInt>,
status_msg: Option<String>,
) -> Result<()> {
) -> Result {
let last_presence = self.get_presence(user_id).await;
let state_changed = match last_presence {
| Err(_) => true,

View File

@@ -55,7 +55,7 @@ impl crate::Service for Service {
}))
}
async fn worker(self: Arc<Self>) -> Result<()> {
async fn worker(self: Arc<Self>) -> Result {
let receiver = self.timer_channel.1.clone();
let mut presence_timers = FuturesUnordered::new();
@@ -99,7 +99,7 @@ impl Service {
/// Pings the presence of the given user in the given room, setting the
/// specified state.
pub async fn ping_presence(&self, user_id: &UserId, new_state: &PresenceState) -> Result<()> {
pub async fn ping_presence(&self, user_id: &UserId, new_state: &PresenceState) -> Result {
const REFRESH_TIMEOUT: u64 = 60 * 1000;
let last_presence = self.db.get_presence(user_id).await;
@@ -140,7 +140,7 @@ impl Service {
currently_active: Option<bool>,
last_active_ago: Option<UInt>,
status_msg: Option<String>,
) -> Result<()> {
) -> Result {
let presence_state = match state.as_str() {
| "" => &PresenceState::Offline, // default an empty string to 'offline'
| &_ => state,
@@ -257,7 +257,7 @@ impl Service {
Ok(event)
}
async fn process_presence_timer(&self, user_id: &OwnedUserId) -> Result<()> {
async fn process_presence_timer(&self, user_id: &OwnedUserId) -> Result {
let mut presence_state = PresenceState::Offline;
let mut last_active_ago = None;
let mut status_msg = None;

View File

@@ -390,8 +390,7 @@ impl Service {
pusher: &Pusher,
tweaks: Vec<Tweak>,
event: &Pdu,
) -> Result
{
) -> Result {
// TODO: email
match &pusher.kind {
| PusherKind::Http(http) => {

View File

@@ -348,7 +348,7 @@ impl super::Service {
Ok(None)
}
fn handle_resolve_error(e: &ResolveError, host: &'_ str) -> Result<()> {
fn handle_resolve_error(e: &ResolveError, host: &'_ str) -> Result {
use hickory_resolver::{ResolveErrorKind::Proto, proto::ProtoErrorKind};
match e.kind() {
@@ -376,7 +376,7 @@ impl super::Service {
}
}
fn validate_dest(&self, dest: &ServerName) -> Result<()> {
fn validate_dest(&self, dest: &ServerName) -> Result {
if dest == self.services.server.name && !self.services.server.config.federation_loopback {
return Err!("Won't send federation request to ourselves");
}
@@ -388,7 +388,7 @@ impl super::Service {
Ok(())
}
fn validate_dest_ip_literal(&self, dest: &ServerName) -> Result<()> {
fn validate_dest_ip_literal(&self, dest: &ServerName) -> Result {
trace!("Destination is an IP literal, checking against IP range denylist.",);
debug_assert!(
dest.is_ip_literal() || !IPAddress::is_valid(dest.host()),
@@ -403,7 +403,7 @@ impl super::Service {
Ok(())
}
pub(crate) fn validate_ip(&self, ip: &IPAddress) -> Result<()> {
pub(crate) fn validate_ip(&self, ip: &IPAddress) -> Result {
if !self.services.client.valid_cidr_range(ip) {
return Err!(BadServerResponse("Not allowed to send requests to this IP"));
}

View File

@@ -64,12 +64,7 @@ impl crate::Service for Service {
impl Service {
#[tracing::instrument(skip(self))]
pub fn set_alias(
&self,
alias: &RoomAliasId,
room_id: &RoomId,
user_id: &UserId,
) -> Result<()> {
pub fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId, user_id: &UserId) -> Result {
if alias == self.services.globals.admin_alias
&& user_id != self.services.globals.server_user
{
@@ -96,7 +91,7 @@ impl Service {
}
#[tracing::instrument(skip(self))]
pub async fn remove_alias(&self, alias: &RoomAliasId, user_id: &UserId) -> Result<()> {
pub async fn remove_alias(&self, alias: &RoomAliasId, user_id: &UserId) -> Result {
if !self.user_can_remove_alias(alias, user_id).await? {
return Err!(Request(Forbidden("User is not permitted to remove this alias.")));
}
@@ -295,7 +290,7 @@ impl Service {
&self,
room_alias: &RoomAliasId,
appservice_info: &Option<RegistrationInfo>,
) -> Result<()> {
) -> Result {
if !self
.services
.globals

View File

@@ -24,7 +24,7 @@ use super::ExtractBody;
#[implement(super::Service)]
#[tracing::instrument(name = "backfill", level = "debug", skip(self))]
pub 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 {
if self
.services
.state_cache
@@ -143,7 +143,7 @@ pub async fn backfill_if_required(&self, room_id: &RoomId, from: PduCount) -> Re
#[implement(super::Service)]
#[tracing::instrument(skip(self, pdu), level = "debug")]
pub async fn backfill_pdu(&self, origin: &ServerName, pdu: Box<RawJsonValue>) -> Result<()> {
pub async fn backfill_pdu(&self, origin: &ServerName, pdu: Box<RawJsonValue>) -> Result {
let (room_id, event_id, value) = self
.services
.event_handler

View File

@@ -51,12 +51,7 @@ impl crate::Service for Service {
impl Service {
/// Sets a user as typing until the timeout timestamp is reached or
/// roomtyping_remove is called.
pub async fn typing_add(
&self,
user_id: &UserId,
room_id: &RoomId,
timeout: u64,
) -> Result<()> {
pub async fn typing_add(&self, user_id: &UserId, room_id: &RoomId, timeout: u64) -> Result {
debug_info!("typing started {user_id:?} in {room_id:?} timeout:{timeout:?}");
// update clients
self.typing
@@ -89,7 +84,7 @@ impl Service {
}
/// Removes a user from typing before the timeout is reached.
pub async fn typing_remove(&self, user_id: &UserId, room_id: &RoomId) -> Result<()> {
pub async fn typing_remove(&self, user_id: &UserId, room_id: &RoomId) -> Result {
debug_info!("typing stopped {user_id:?} in {room_id:?}");
// update clients
self.typing
@@ -131,7 +126,7 @@ impl Service {
}
/// Makes sure that typing events with old timestamps get removed.
async fn typings_maintain(&self, room_id: &RoomId) -> Result<()> {
async fn typings_maintain(&self, room_id: &RoomId) -> Result {
let current_timestamp = utils::millis_since_unix_epoch();
let mut removable = Vec::new();
@@ -226,12 +221,7 @@ impl Service {
})
}
async fn federation_send(
&self,
room_id: &RoomId,
user_id: &UserId,
typing: bool,
) -> Result<()> {
async fn federation_send(&self, room_id: &RoomId, user_id: &UserId, typing: bool) -> Result {
debug_assert!(
self.services.globals.user_is_local(user_id),
"tried to broadcast typing status of remote user",

View File

@@ -275,7 +275,7 @@ impl Service {
}
#[tracing::instrument(skip(self, room_id), level = "debug")]
pub async fn flush_room(&self, room_id: &RoomId) -> Result<()> {
pub async fn flush_room(&self, room_id: &RoomId) -> Result {
let servers = self
.services
.state_cache
@@ -286,7 +286,7 @@ impl Service {
}
#[tracing::instrument(skip(self, servers), level = "debug")]
pub async fn flush_servers<'a, S>(&self, servers: S) -> Result<()>
pub async fn flush_servers<'a, S>(&self, servers: S) -> Result
where
S: Stream<Item = &'a ServerName> + Send + 'a,
{

View File

@@ -26,7 +26,7 @@ pub(crate) trait Service: Any + Send + Sync {
/// Implement the service's worker loop. The service manager spawns a
/// task and calls this function after all services have been built.
async fn worker(self: Arc<Self>) -> Result<()> { Ok(()) }
async fn worker(self: Arc<Self>) -> Result { Ok(()) }
/// Interrupt the service. This is sent to initiate a graceful shutdown.
/// The service worker should return from its work loop.

View File

@@ -161,7 +161,7 @@ impl Services {
debug_info!("Services shutdown complete.");
}
pub async fn poll(&self) -> Result<()> {
pub async fn poll(&self) -> Result {
if let Some(manager) = self.manager.lock().await.as_ref() {
return manager.poll().await;
}