You've already forked AstralRinth
forked from didirus/AstralRinth
Wire Profile Backend to Frontend (#71)
* Search updates * fixes2 * Some more work * start instance page wiring * Pack installation + Profile viewing * Remove print statement * Fix disappearing profiles * fix compile err * Finish Instance Running * remove print statement * fix prettier * Fix clippy + early return
This commit is contained in:
@@ -1,25 +1,51 @@
|
||||
//! Functions for fetching infromation from the Internet
|
||||
use crate::config::REQWEST_CLIENT;
|
||||
use bytes::Bytes;
|
||||
use reqwest::Method;
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tokio::sync::Semaphore;
|
||||
use tokio::{
|
||||
fs::{self, File},
|
||||
io::AsyncWriteExt,
|
||||
sync::SemaphorePermit,
|
||||
};
|
||||
|
||||
const FETCH_ATTEMPTS: usize = 3;
|
||||
|
||||
/// Downloads a file with retry and checksum functionality
|
||||
#[tracing::instrument(skip(_permit))]
|
||||
pub async fn fetch<'a>(
|
||||
pub async fn fetch(
|
||||
url: &str,
|
||||
sha1: Option<&str>,
|
||||
_permit: &SemaphorePermit<'a>,
|
||||
) -> crate::Result<bytes::Bytes> {
|
||||
semaphore: &Semaphore,
|
||||
) -> crate::Result<Bytes> {
|
||||
fetch_advanced(Method::GET, url, sha1, semaphore).await
|
||||
}
|
||||
|
||||
pub async fn fetch_json<T>(
|
||||
method: Method,
|
||||
url: &str,
|
||||
sha1: Option<&str>,
|
||||
semaphore: &Semaphore,
|
||||
) -> crate::Result<T>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
let result = fetch_advanced(method, url, sha1, semaphore).await?;
|
||||
let value = serde_json::from_slice(&result)?;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
/// Downloads a file with retry and checksum functionality
|
||||
#[tracing::instrument(skip(semaphore))]
|
||||
pub async fn fetch_advanced(
|
||||
method: Method,
|
||||
url: &str,
|
||||
sha1: Option<&str>,
|
||||
semaphore: &Semaphore,
|
||||
) -> crate::Result<Bytes> {
|
||||
let _permit = semaphore.acquire().await?;
|
||||
for attempt in 1..=(FETCH_ATTEMPTS + 1) {
|
||||
let result = REQWEST_CLIENT.get(url).send().await;
|
||||
let result = REQWEST_CLIENT.request(method.clone(), url).send().await;
|
||||
|
||||
match result {
|
||||
Ok(x) => {
|
||||
@@ -50,7 +76,9 @@ pub async fn fetch<'a>(
|
||||
}
|
||||
}
|
||||
Err(_) if attempt <= 3 => continue,
|
||||
Err(err) => return Err(err.into()),
|
||||
Err(err) => {
|
||||
return Err(err.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,12 +86,12 @@ pub async fn fetch<'a>(
|
||||
}
|
||||
|
||||
/// Downloads a file from specified mirrors
|
||||
#[tracing::instrument(skip(permit))]
|
||||
pub async fn fetch_mirrors<'a>(
|
||||
#[tracing::instrument(skip(semaphore))]
|
||||
pub async fn fetch_mirrors(
|
||||
mirrors: &[&str],
|
||||
sha1: Option<&str>,
|
||||
permit: &SemaphorePermit<'a>,
|
||||
) -> crate::Result<bytes::Bytes> {
|
||||
semaphore: &Semaphore,
|
||||
) -> crate::Result<Bytes> {
|
||||
if mirrors.is_empty() {
|
||||
return Err(crate::ErrorKind::InputError(
|
||||
"No mirrors provided!".to_string(),
|
||||
@@ -72,7 +100,7 @@ pub async fn fetch_mirrors<'a>(
|
||||
}
|
||||
|
||||
for (index, mirror) in mirrors.iter().enumerate() {
|
||||
let result = fetch(mirror, sha1, permit).await;
|
||||
let result = fetch(mirror, sha1, semaphore).await;
|
||||
|
||||
if result.is_ok() || (result.is_err() && index == (mirrors.len() - 1)) {
|
||||
return result;
|
||||
@@ -82,28 +110,29 @@ pub async fn fetch_mirrors<'a>(
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(bytes, _permit))]
|
||||
#[tracing::instrument(skip(bytes, semaphore))]
|
||||
pub async fn write<'a>(
|
||||
path: &Path,
|
||||
bytes: &[u8],
|
||||
_permit: &SemaphorePermit<'a>,
|
||||
semaphore: &Semaphore,
|
||||
) -> crate::Result<()> {
|
||||
let _permit = semaphore.acquire().await?;
|
||||
if let Some(parent) = path.parent() {
|
||||
fs::create_dir_all(parent).await?;
|
||||
}
|
||||
|
||||
let mut file = File::create(path).await?;
|
||||
log::debug!("Done writing file {}", path.display());
|
||||
file.write_all(bytes).await?;
|
||||
log::debug!("Done writing file {}", path.display());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(bytes, permit))]
|
||||
pub async fn write_cached_icon<'a>(
|
||||
#[tracing::instrument(skip(bytes, semaphore))]
|
||||
pub async fn write_cached_icon(
|
||||
icon_path: &str,
|
||||
cache_dir: &Path,
|
||||
bytes: Bytes,
|
||||
permit: &SemaphorePermit<'a>,
|
||||
semaphore: &Semaphore,
|
||||
) -> crate::Result<PathBuf> {
|
||||
let extension = Path::new(&icon_path).extension().and_then(OsStr::to_str);
|
||||
let hash = sha1_async(bytes.clone()).await?;
|
||||
@@ -113,8 +142,9 @@ pub async fn write_cached_icon<'a>(
|
||||
hash
|
||||
});
|
||||
|
||||
write(&path, &bytes, permit).await?;
|
||||
write(&path, &bytes, semaphore).await?;
|
||||
|
||||
let path = dunce::canonicalize(path)?;
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user