feat: install flow improvements (#6669)

* feat: better error handling + copy details btn for info

* refactor: clean up error handling into diagnostics

* feat: extra info for failure states + queuing properly

* fix: cleanup

* fix: lint

* fix: fmt

* fix: cleanup

* fix: cleanup

* fix: lint

* feat: use bon builder
This commit is contained in:
Calum H.
2026-07-10 11:54:56 +00:00
committed by GitHub
parent 57a977f7f3
commit c07727aa49
44 changed files with 2572 additions and 480 deletions
+74 -2
View File
@@ -1,8 +1,8 @@
//! Functions for fetching information from the Internet
use super::io::{self, IOError};
use crate::ErrorKind;
use crate::event::LoadingBarId;
use crate::event::emit::emit_loading;
use crate::{ErrorKind, LabrinthError};
use bytes::Bytes;
use chrono::{DateTime, TimeDelta, Utc};
use eyre::{Context, eyre};
@@ -190,6 +190,8 @@ static GLOBAL_FETCH_FENCE: LazyLock<FetchFence> =
fn reqwest_client_builder() -> reqwest::ClientBuilder {
reqwest::Client::builder()
.connect_timeout(time::Duration::from_secs(15))
.read_timeout(time::Duration::from_secs(30))
.tcp_keepalive(Some(time::Duration::from_secs(10)))
.user_agent(crate::launcher_user_agent())
}
@@ -267,6 +269,34 @@ pub async fn fetch_with_client(
.await
}
#[tracing::instrument(skip(semaphore, progress))]
pub async fn fetch_with_client_progress(
url: &str,
sha1: Option<&str>,
download_meta: Option<&DownloadMeta>,
uri_path: Option<&'static str>,
semaphore: &FetchSemaphore,
exec: impl sqlx::Executor<'_, Database = sqlx::Sqlite>,
client: &reqwest::Client,
progress: Option<&mut FetchProgressFn<'_>>,
) -> crate::Result<Bytes> {
fetch_advanced_with_client_and_progress(
Method::GET,
url,
sha1,
None,
None,
download_meta,
None,
uri_path,
semaphore,
exec,
client,
progress,
)
.await
}
#[tracing::instrument(skip(json_body, semaphore))]
pub async fn fetch_json<T>(
method: Method,
@@ -466,8 +496,13 @@ async fn fetch_advanced_with_client_and_progress(
if resp.status().is_client_error()
|| resp.status().is_server_error()
{
let status = resp.status();
let backup_error = resp.error_for_status_ref().unwrap_err();
if let Ok(error) = resp.json().await {
if let Ok(mut error) = resp.json::<LabrinthError>().await {
error.status = Some(status.as_u16());
error.method = Some(method.as_str().to_string());
error.url = Some(url.to_string());
error.route = uri_path.map(str::to_string);
return Err(ErrorKind::LabrinthError(error).into());
}
return Err(backup_error.into());
@@ -599,6 +634,43 @@ pub async fn fetch_mirrors(
unreachable!()
}
#[tracing::instrument(skip(semaphore, progress))]
pub async fn fetch_mirrors_with_progress(
mirrors: &[&str],
sha1: Option<&str>,
download_meta: Option<&DownloadMeta>,
uri_path: Option<&'static str>,
semaphore: &FetchSemaphore,
exec: impl sqlx::Executor<'_, Database = sqlx::Sqlite> + Copy,
mut progress: Option<&mut FetchProgressFn<'_>>,
) -> crate::Result<Bytes> {
if mirrors.is_empty() {
return Err(
ErrorKind::InputError("No mirrors provided!".to_string()).into()
);
}
for (index, mirror) in mirrors.iter().enumerate() {
let result = fetch_with_client_progress(
mirror,
sha1,
download_meta,
uri_path,
semaphore,
exec,
&REQWEST_CLIENT,
progress.as_deref_mut(),
)
.await;
if result.is_ok() || (result.is_err() && index == (mirrors.len() - 1)) {
return result;
}
}
unreachable!()
}
/// Posts a JSON to a URL
#[tracing::instrument(skip(json_body, semaphore))]
pub async fn post_json(