mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-11-14 04:37:00 +00:00
feat: Move & destructure servers-in-back command to federation group
This commit is contained in:
4 files changed
+164
-72
No files matched your search
@@ -1124,60 +1124,4 @@ impl crate::Context<'_> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) async fn servers_in_backoff(
|
||||
&self,
|
||||
room_id: Option<OwnedRoomId>,
|
||||
name: Option<OwnedServerName>,
|
||||
) -> Result {
|
||||
let backoff_map = self.services.federation.remote_health();
|
||||
|
||||
if backoff_map.is_empty() {
|
||||
return self.write_str("No servers are currently in backoff.").await;
|
||||
}
|
||||
|
||||
let stale_map = self.services.federation.stale_destinations();
|
||||
|
||||
if let Some(specific_server_name) = name {
|
||||
let entry = backoff_map.get(&specific_server_name);
|
||||
return match entry {
|
||||
| Some((retries, next_retry)) =>
|
||||
self.write_str(&format!(
|
||||
"{specific_server_name}: {retries} retries, next retry at {next_retry}"
|
||||
))
|
||||
.await,
|
||||
| None =>
|
||||
self.write_str(&format!("Server {specific_server_name} is not in backoff."))
|
||||
.await,
|
||||
};
|
||||
}
|
||||
|
||||
self.write_str("| Server Name | Retries | Next connection attempt | Is stale |\n")
|
||||
.await?;
|
||||
self.write_str("| ----------- | ------- | ----------------------- | -------- |\n")
|
||||
.await?;
|
||||
|
||||
if let Some(specific_room) = room_id {
|
||||
let mut servers_in_room =
|
||||
self.services.rooms.state_cache.room_servers(&specific_room);
|
||||
while let Some(server_name) = servers_in_room.next().await {
|
||||
let Some((retries, retry_at)) = backoff_map.get(&server_name) else { continue };
|
||||
let is_stale = if stale_map.contains(&server_name) { "Yes" } else { "No" };
|
||||
self.write_str(&format!(
|
||||
"| {server_name} | {retries} | {retry_at} | {is_stale} |\n"
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for (server_name, (retries, retry_at)) in &backoff_map {
|
||||
let is_stale = if stale_map.contains(server_name) { "Yes" } else { "No" };
|
||||
self.write_str(&format!("| {server_name} | {retries} | {retry_at} | {is_stale} |\n"))
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -208,20 +208,6 @@ pub enum DebugCommand {
|
||||
room_id: OwnedRoomId,
|
||||
},
|
||||
|
||||
/// Lists remote servers that are currently in a "backoff" state.
|
||||
///
|
||||
/// Servers in this list will not be contacted until the retry time elapses,
|
||||
/// or they make contact first.
|
||||
///
|
||||
/// "Stale" indicates that routing information may be out of date, and the
|
||||
/// remote will be re-resolved immediately before the next contact attempt.
|
||||
ServersInBackoff {
|
||||
#[arg(short, long, alias = "room")]
|
||||
room_id: Option<OwnedRoomId>,
|
||||
#[arg(short, long)]
|
||||
name: Option<OwnedServerName>,
|
||||
},
|
||||
|
||||
/// Developer test stubs
|
||||
#[command(subcommand)]
|
||||
#[allow(non_snake_case)]
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use clap::Subcommand;
|
||||
use conduwuit::Result;
|
||||
use conduwuit_macros::admin_command_dispatch;
|
||||
use futures::StreamExt;
|
||||
use ruma::{OwnedRoomOrAliasId, OwnedServerName};
|
||||
|
||||
#[admin_command_dispatch]
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum HealthCommand {
|
||||
/// Lists all servers that are currently marked as unhealthy (i.e. we
|
||||
/// previously failed to establish direct federation and have not succeeded
|
||||
/// since).
|
||||
#[clap(name = "list")]
|
||||
ListUnhealthyServers {
|
||||
/// An optional filter to only check servers that are in a specific room
|
||||
/// (ID or alias).
|
||||
room: Option<OwnedRoomOrAliasId>,
|
||||
},
|
||||
|
||||
/// Displays the current health status of the given remote server.
|
||||
#[clap(name = "status")]
|
||||
ServerHealthStatus {
|
||||
server_name: OwnedServerName,
|
||||
},
|
||||
|
||||
/// Forces the server to consider the remote server healthy.
|
||||
///
|
||||
/// This is generally unnecessary as this already happens when the remote
|
||||
/// server makes contact with this server, or if this server successfully
|
||||
/// makes a request to the remote server after the backoff window.
|
||||
ForceHealthy {
|
||||
server_name: OwnedServerName,
|
||||
},
|
||||
|
||||
/// Forces the server to consider the remote server unhealthy.
|
||||
///
|
||||
/// This is generally unnecessary as this already happens when the remote
|
||||
/// server fails to resolve or connect, or returns unusual errors.
|
||||
/// If you are looking to stop contacting a specific server, take a look at
|
||||
/// the `forbidden_remote_server_names` configuration option.
|
||||
ForceUnhealthy {
|
||||
server_name: OwnedServerName,
|
||||
#[arg(long)]
|
||||
stale: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl crate::Context<'_> {
|
||||
pub(super) async fn list_unhealthy_servers(
|
||||
&self,
|
||||
room: Option<OwnedRoomOrAliasId>,
|
||||
) -> Result {
|
||||
let unhealthy = self.services.federation.remote_health();
|
||||
|
||||
if unhealthy.is_empty() {
|
||||
return self
|
||||
.write_str("No servers are currently tracked as unhealthy.")
|
||||
.await;
|
||||
}
|
||||
|
||||
let stale_destinations = self.services.federation.stale_destinations();
|
||||
|
||||
let mut candidates: Vec<_> = if let Some(room) = room {
|
||||
let room_id = self.services.rooms.alias.resolve(&room).await?;
|
||||
self.services
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_servers(&room_id)
|
||||
.collect()
|
||||
.await
|
||||
} else {
|
||||
unhealthy
|
||||
.keys()
|
||||
.chain(stale_destinations.iter())
|
||||
.cloned()
|
||||
.collect()
|
||||
};
|
||||
candidates.retain(|name| unhealthy.contains_key(name));
|
||||
candidates.sort();
|
||||
candidates.dedup();
|
||||
if candidates.is_empty() {
|
||||
return self
|
||||
.write_str("No servers are currently unhealthy meeting the given criteria.")
|
||||
.await;
|
||||
}
|
||||
for server_name in candidates {
|
||||
let Some((retries, retry_at)) = unhealthy.get(&server_name) else { continue };
|
||||
let is_stale = if stale_destinations.contains(&server_name) {
|
||||
"Yes"
|
||||
} else {
|
||||
"No"
|
||||
};
|
||||
self.write_str(&format!("| {server_name} | {retries} | {retry_at} | {is_stale} |\n"))
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) async fn server_health_status(&self, server_name: OwnedServerName) -> Result {
|
||||
let stale = self
|
||||
.services
|
||||
.federation
|
||||
.stale_destinations()
|
||||
.contains(&server_name);
|
||||
let Some((retries, retry_at_ts)) = self
|
||||
.services
|
||||
.federation
|
||||
.remote_health()
|
||||
.get(&server_name)
|
||||
.copied()
|
||||
else {
|
||||
return self
|
||||
.write_str(&if stale {
|
||||
format!(
|
||||
"{server_name} is currently healthy, but may have stale routing \
|
||||
information."
|
||||
)
|
||||
} else {
|
||||
format!("{server_name} is currently healthy.")
|
||||
})
|
||||
.await;
|
||||
};
|
||||
|
||||
let state = if stale {
|
||||
"unhealthy with potentially stale routing information"
|
||||
} else {
|
||||
"unhealthy"
|
||||
};
|
||||
self.write_str(&format!(
|
||||
"{server_name} is currently {state}: {retries} consecutive connections have \
|
||||
failed,and no new connection will be attempted for another {}.",
|
||||
conduwuit::utils::time::pretty(Duration::from_millis(retry_at_ts)),
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
pub(super) async fn force_healthy(&self, server_name: OwnedServerName) -> Result {
|
||||
self.services.federation.mark_healthy(&server_name);
|
||||
self.write_str("Done.").await
|
||||
}
|
||||
|
||||
pub(super) async fn force_unhealthy(
|
||||
&self,
|
||||
server_name: OwnedServerName,
|
||||
stale: bool,
|
||||
) -> Result {
|
||||
if stale {
|
||||
self.services
|
||||
.federation
|
||||
.mark_destination_stale(&server_name);
|
||||
}
|
||||
self.services.federation.hit_unhealthy(server_name);
|
||||
self.write_str("Done.").await
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
mod commands;
|
||||
mod health;
|
||||
|
||||
use clap::Subcommand;
|
||||
use conduwuit::Result;
|
||||
use ruma::{OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName, OwnedUserId};
|
||||
use ruma::{OwnedRoomOrAliasId, OwnedServerName};
|
||||
|
||||
use crate::admin_command_dispatch;
|
||||
use crate::{admin_command_dispatch, federation::health::HealthCommand};
|
||||
|
||||
#[admin_command_dispatch]
|
||||
#[derive(Debug, Subcommand)]
|
||||
@@ -49,4 +50,7 @@ pub enum FederationCommand {
|
||||
Ping {
|
||||
server_name: OwnedServerName,
|
||||
},
|
||||
|
||||
#[command(subcommand)]
|
||||
Health(HealthCommand),
|
||||
}
|
||||
Reference in new issue
Block a user