fix: app cache and other issues (#5460)

* fixes

* #[serde(untagged)] my BEHATED (still kinda broken)

* remove unused hasContent ref

* clean up code in fetch instance

* ping 3 times for average latency

* fix: pinging to be more accurate

TCP_NODELAY — Set on the TCP stream right after connect, preventing Nagle's algorithm from buffering the small ping packet (could save up to ~40ms)

Instant over Utc::now() — Switched to monotonic std::time::Instant for timing, which is more precise and designed for measuring elapsed time (still using chrono just for the ping magic value)

* delete useFetch util and just use native fetch

* rename worlds until functions for more clarity

* fix lint

* fix cache.rs logic

* make backend ping use both impls

* Add optional timeout to server ping

* fix gallery appearing in nav with no items

* remove EU countries and add EU option for server country

* add uk to europe

---------

Co-authored-by: aecsocket <aecsocket@tutanota.com>
This commit is contained in:
Truman Gao
2026-03-03 10:41:12 -08:00
committed by GitHub
parent 211ec20970
commit 0029a22569
17 changed files with 468 additions and 272 deletions

View File

@@ -54,7 +54,7 @@ impl ServerPingQueue {
let mut retries = ENV.SERVER_PING_RETRIES;
let result = loop {
match ping_server(&address, port).await {
match ping_server(&address, port, None).await {
Ok(ping) => {
info!(?ping, "Received successful ping");
break Ok(ping);
@@ -252,39 +252,15 @@ impl ServerPingQueue {
pub async fn ping_server(
address: &str,
port: u16,
timeout: Option<Duration>,
) -> eyre::Result<exp::minecraft::JavaServerPingData> {
let start = Instant::now();
let timeout = Duration::from_millis(ENV.SERVER_PING_TIMEOUT_MS);
let default_duration = Duration::from_millis(ENV.SERVER_PING_TIMEOUT_MS);
let timeout = timeout
.map(|duration| duration.min(default_duration))
.unwrap_or(default_duration);
let task1 = async move {
let conn = async_minecraft_ping::ConnectionConfig::build(address)
.with_port(port)
.connect()
.await
.wrap_err("failed to connect to server")?;
let status = conn
.status()
.await
.wrap_err("failed to get server status")?
.status;
debug!("Successful ping with `async_minecraft_ping`");
eyre::Ok(exp::minecraft::JavaServerPingData {
latency: start.elapsed(),
version_name: status.version.name,
version_protocol: status.version.protocol,
description: match status.description {
ServerDescription::Plain(text)
| ServerDescription::Object { text } => text,
},
players_online: status.players.online,
players_max: status.players.max,
})
};
let task1 = tokio::time::timeout(timeout, task1);
let task2 = async move {
let task_ep = async move {
fn map_component(c: elytra_ping::parse::TextComponent) -> String {
match c {
elytra_ping::parse::TextComponent::Plain(t) => t,
@@ -303,7 +279,6 @@ pub async fn ping_server(
elytra_ping::ping_or_timeout((address.to_string(), port), timeout)
.await?;
debug!("Successful ping with `elytra_ping`");
eyre::Ok(exp::minecraft::JavaServerPingData {
latency,
version_name: result
@@ -326,15 +301,54 @@ pub async fn ping_server(
})
};
async move {
if let Ok(t) = task1
.await
.wrap_err("failed to ping with `async_minecraft_ping`")?
{
return Ok(t);
}
let task_amp = async move {
let task = async move {
let conn = async_minecraft_ping::ConnectionConfig::build(address)
.with_port(port)
.connect()
.await
.wrap_err("failed to connect to server")?;
task2.await.wrap_err("failed to ping with `elytra_ping`")
let status = conn
.status()
.await
.wrap_err("failed to get server status")?
.status;
eyre::Ok(exp::minecraft::JavaServerPingData {
latency: start.elapsed(),
version_name: status.version.name,
version_protocol: status.version.protocol,
description: match status.description {
ServerDescription::Plain(text)
| ServerDescription::Object { text } => text,
},
players_online: status.players.online,
players_max: status.players.max,
})
};
tokio::time::timeout(timeout, task)
.await
.map_err(eyre::Error::new)
.flatten()
};
async move {
let (result_ep, result_amp) = (task_ep.await, task_amp.await);
let result_ep = result_ep
.inspect(|_| debug!("Successful ping with `elytra_ping`"))
.inspect_err(|err| {
debug!("Failed to ping with `elytra_ping`: {err:#}")
});
let result_amp = result_amp
.inspect(|_| debug!("Successful ping with `async_minecraft_ping`"))
.inspect_err(|err| {
debug!("Failed to ping with `async_minecraft_ping`: {err:#}")
});
result_ep.or(result_amp)
}
.await
}
@@ -359,11 +373,20 @@ mod tests {
#[actix_rt::test]
async fn test_ping_server_success() {
let _status = ping_server("mc.hypixel.net", 25565).await.unwrap();
let _status = ping_server("mc.hypixel.net", 25565, None).await.unwrap();
}
#[actix_rt::test]
async fn test_ping_server_invalid_address() {
_ = ping_server("invalid.invalid", 25565).await.unwrap_err();
_ = ping_server("invalid.invalid", 25565, None)
.await
.unwrap_err();
}
#[actix_rt::test]
async fn test_ping_zero_timeout() {
_ = ping_server("hypixel.net", 25565, Some(Duration::ZERO))
.await
.unwrap_err();
}
}

View File

@@ -1,3 +1,5 @@
use std::time::Duration;
use actix_web::{HttpRequest, post, web};
use serde::{Deserialize, Serialize};
@@ -18,6 +20,7 @@ pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) {
pub struct PingRequest {
pub address: String,
pub port: u16,
pub timeout_ms: Option<u64>,
}
#[utoipa::path]
@@ -38,7 +41,8 @@ pub async fn ping_minecraft_java(
)
.await?;
server_ping::ping_server(&request.address, request.port)
let timeout = request.timeout_ms.map(Duration::from_millis);
server_ping::ping_server(&request.address, request.port, timeout)
.await
.wrap_request_err("failed to ping server")?;