mirror of
https://github.com/modrinth/code.git
synced 2026-08-27 10:04:52 +00:00
fix: memory issues when importing giant mrpack files (#6278)
* feat: dont load mrpacks into memory if they are local imports * fix: frontend
This commit is contained in:
@@ -8,10 +8,9 @@ use crate::state::{
|
||||
SideType,
|
||||
};
|
||||
use crate::util::fetch::{
|
||||
DownloadMeta, DownloadReason, fetch, fetch_advanced, write_cached_icon,
|
||||
DownloadMeta, DownloadReason, fetch, fetch_advanced, sha1_file_async,
|
||||
write_cached_icon,
|
||||
};
|
||||
use crate::util::io;
|
||||
|
||||
use path_util::SafeRelativeUtf8UnixPathBuf;
|
||||
use reqwest::Method;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -134,12 +133,22 @@ impl Default for CreatePackProfile {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum CreatePackFile {
|
||||
Bytes(bytes::Bytes),
|
||||
// Local packs can be larger than available memory, so keep them file-backed.
|
||||
Path(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CreatePack {
|
||||
pub file: bytes::Bytes,
|
||||
pub file: CreatePackFile,
|
||||
pub description: CreatePackDescription,
|
||||
}
|
||||
|
||||
// The hash lookup only gates the unknown-pack warning, so avoid a long blocking scan for huge local packs.
|
||||
const MAX_LOCAL_FILE_HASH_LOOKUP_SIZE: u64 = 1024 * 1024 * 1024;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CreatePackDescription {
|
||||
pub icon: Option<PathBuf>,
|
||||
@@ -176,28 +185,31 @@ pub async fn get_profile_from_pack(
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
let state = State::get().await?;
|
||||
let file_bytes = io::read(&path).await?;
|
||||
let hash =
|
||||
crate::util::fetch::sha1_async(bytes::Bytes::from(file_bytes))
|
||||
.await?;
|
||||
let is_known_file = match CachedEntry::get_file_many(
|
||||
&[&hash],
|
||||
Some(CacheBehaviour::StaleWhileRevalidateSkipOffline),
|
||||
&state.pool,
|
||||
&state.api_semaphore,
|
||||
)
|
||||
.await
|
||||
let is_known_file = if tokio::fs::metadata(&path).await?.len()
|
||||
<= MAX_LOCAL_FILE_HASH_LOOKUP_SIZE
|
||||
{
|
||||
Ok(files) => !files.is_empty(),
|
||||
Err(err) => {
|
||||
tracing::warn!(
|
||||
"Failed to check Modrinth file hash for {}: {}",
|
||||
path.display(),
|
||||
err
|
||||
);
|
||||
false
|
||||
let state = State::get().await?;
|
||||
let (_, hash) = sha1_file_async(&path).await?;
|
||||
match CachedEntry::get_file_many(
|
||||
&[&hash],
|
||||
Some(CacheBehaviour::StaleWhileRevalidateSkipOffline),
|
||||
&state.pool,
|
||||
&state.api_semaphore,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(files) => !files.is_empty(),
|
||||
Err(err) => {
|
||||
tracing::warn!(
|
||||
"Failed to check Modrinth file hash for {}: {}",
|
||||
path.display(),
|
||||
err
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
Ok(CreatePackProfile {
|
||||
@@ -380,7 +392,7 @@ pub async fn generate_pack_from_version_id(
|
||||
}
|
||||
|
||||
Ok(CreatePack {
|
||||
file,
|
||||
file: CreatePackFile::Bytes(file),
|
||||
description: CreatePackDescription {
|
||||
icon,
|
||||
override_title: Some(title),
|
||||
@@ -398,9 +410,8 @@ pub async fn generate_pack_from_file(
|
||||
path: PathBuf,
|
||||
profile_path: String,
|
||||
) -> crate::Result<CreatePack> {
|
||||
let file = io::read(&path).await?;
|
||||
Ok(CreatePack {
|
||||
file: bytes::Bytes::from(file),
|
||||
file: CreatePackFile::Path(path),
|
||||
description: CreatePackDescription {
|
||||
icon: None,
|
||||
override_title: None,
|
||||
|
||||
Reference in New Issue
Block a user