From 6fc741f7c0c9f9aa1fd840834681c503d231bf0f Mon Sep 17 00:00:00 2001 From: aecsocket <43144841+aecsocket@users.noreply.github.com> Date: Thu, 25 Jun 2026 19:50:04 +0100 Subject: [PATCH] fix: file scan fix v2 (#6504) * fix: file attribution scanning not marking completed files * prepare * Handle file scan failures gracefully with tracking * conditional * add more logging * remove leftover files --- apps/labrinth/src/queue/file_scan.rs | 80 +++++++++++++++++++++------- 1 file changed, 61 insertions(+), 19 deletions(-) diff --git a/apps/labrinth/src/queue/file_scan.rs b/apps/labrinth/src/queue/file_scan.rs index 0a47f49307..33052134c8 100644 --- a/apps/labrinth/src/queue/file_scan.rs +++ b/apps/labrinth/src/queue/file_scan.rs @@ -147,20 +147,28 @@ async fn scan_pending_files_batch( } let mut scanned_count = 0; - let mut first_err = None; + let mut errors = Vec::new(); for task in tasks { match task.await.wrap_err("joining file scan task")? { Ok(count) => scanned_count += count, Err(err) => { - if first_err.is_none() { - first_err = Some(err); - } + errors.push(err); } } } - if let Some(err) = first_err { - return Err(err).wrap_err("scanning pending file chunk"); + if !errors.is_empty() { + let error_count = errors.len(); + let error_messages = errors + .into_iter() + .enumerate() + .map(|(index, err)| format!("chunk {}: {err:?}", index + 1)) + .collect::>() + .join("\n\n"); + + return Err(eyre!( + "failed to scan {error_count} pending file chunks:\n\n{error_messages}" + )); } if fetched_count > 0 && scanned_count == 0 { @@ -235,6 +243,7 @@ async fn scan_pending_files_chunk( txn.commit() .await .wrap_err("committing file scan transaction")?; + log_marked_override_projects(&resolved); eyre::Ok(()) } @@ -309,6 +318,7 @@ async fn scan_file_inner( .wrap_err_with(|| { eyre!("persisting attribution results for file {file_id:?}") })?; + log_marked_override_projects(&resolved); } Ok(()) @@ -432,6 +442,33 @@ pub enum OverrideResolution { Unknown, } +fn log_marked_override_projects( + resolved: &HashMap, +) { + let mut projects = resolved + .values() + .filter_map(|resolution| match resolution { + OverrideResolution::ExternalLicense { + flame_project: Some(flame_project), + .. + } + | OverrideResolution::Flame(flame_project) => { + Some(format!("{} ({})", flame_project.title, flame_project.id)) + } + OverrideResolution::OnModrinth + | OverrideResolution::ExternalLicense { .. } + | OverrideResolution::Unknown => None, + }) + .collect::>(); + + projects.sort(); + projects.dedup(); + + if !projects.is_empty() { + info!(override_projects = ?projects, "Marked projects as overrides"); + } +} + const OVERRIDE_PREFIXES: &[&str] = &[ "overrides/mods", "client-overrides/mods", @@ -442,6 +479,23 @@ const OVERRIDE_PREFIXES: &[&str] = &[ "client-overrides/resourcepacks", ]; +fn should_scan(name: &str) -> bool { + let should_skip = name.starts_with("mods/.connector/") + || name.starts_with(".sable/natives/") + || name.starts_with("local/crash_assistant/") + || name.starts_with("mods/mcef-libraries/") + || name.starts_with("mods/mcef-cache/") + || name.starts_with("config/super_resolution/libraries/") + || name.starts_with("config/Veinminer/update/") + || name.starts_with("config/epicfight/native/") + || name.starts_with("essential/") + || name.ends_with(".rpo") + || name.ends_with(".txt"); + let is_archive = name.contains(".jar") || name.contains(".zip"); + + is_archive && !should_skip +} + fn extract_override_files(data: &[u8]) -> Result> { let reader = Cursor::new(data); let mut zip = @@ -466,19 +520,7 @@ fn extract_override_files(data: &[u8]) -> Result> { continue; } - let should_skip = name.starts_with("mods/.connector/") - || name.starts_with(".sable/natives/") - || name.starts_with("local/crash_assistant/") - || name.starts_with("mods/mcef-libraries/") - || name.starts_with("mods/mcef-cache/") - || name.starts_with("config/super_resolution/libraries/") - || name.starts_with("config/Veinminer/update/") - || name.starts_with("config/epicfight/native/") - || name.starts_with("essential/") - || name.ends_with(".rpo") - || name.ends_with(".txt"); - let should_scan = name.contains(".jar") || name.contains(".zip"); - if should_scan && !should_skip { + if !should_scan(&name) { continue; }