From 8ddd3bd64b2e5368f98b584acb6db4eb7b426cca Mon Sep 17 00:00:00 2001 From: Connor Johnstone Date: Tue, 24 Mar 2026 21:32:25 -0400 Subject: [PATCH] speedup on tagging --- src/file_tags.rs | 4 +++- src/tagger.rs | 42 +++++++++++++++++------------------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/file_tags.rs b/src/file_tags.rs index 2339868..c57bc36 100644 --- a/src/file_tags.rs +++ b/src/file_tags.rs @@ -31,7 +31,9 @@ pub fn write_tags( ) -> TagResult<()> { let path = Path::new(file_path); - let tagged_file = Probe::open(path)?.options(ParseOptions::default()).read()?; + let tagged_file = Probe::open(path)? + .options(ParseOptions::new().read_properties(false)) + .read()?; // Determine the tag type to use let tag_type = tagged_file diff --git a/src/tagger.rs b/src/tagger.rs index be92c53..ff7f055 100644 --- a/src/tagger.rs +++ b/src/tagger.rs @@ -1,27 +1,18 @@ -use std::fmt; - -use sea_orm::{ActiveValue::Set, DatabaseConnection, NotSet}; - +use sea_orm::{ActiveValue::NotSet, ActiveValue::Set, DatabaseConnection}; +use shanty_data::MetadataFetcher as MetadataProvider; use shanty_db::entities::track; use shanty_db::queries; use crate::error::TagResult; use crate::file_tags; use crate::matcher::{self, ScoredMatch}; -use shanty_data::MetadataFetcher as MetadataProvider; -/// Configuration for a tagging operation. pub struct TagConfig { - /// If true, show what would change without writing to DB or files. pub dry_run: bool, - /// If true, write updated tags back to the music files. pub write_tags: bool, - /// Minimum match confidence (0.0 - 1.0). pub confidence: f64, } -/// Statistics from a completed tagging run. -#[derive(Debug, Default, Clone)] pub struct TagStats { pub tracks_processed: u64, pub tracks_matched: u64, @@ -30,8 +21,8 @@ pub struct TagStats { pub tracks_errored: u64, } -impl fmt::Display for TagStats { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl std::fmt::Display for TagStats { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "processed: {}, matched: {}, updated: {}, skipped: {}, errors: {}", @@ -198,30 +189,33 @@ fn log_match(track: &track::Model, best: &ScoredMatch) { confidence = format!("{:.2}", best.confidence), matched_title = %best.recording.title, matched_artist = %best.recording.artist, - release = best.best_release.as_ref().map(|r| r.title.as_str()).unwrap_or("(none)"), - "match found" + "matched" ); } -/// Run tagging on all untagged tracks or a specific track. +/// Run tagging on a single track (by ID) or all tracks needing metadata. pub async fn run_tagging( conn: &DatabaseConnection, provider: &impl MetadataProvider, config: &TagConfig, track_id: Option, ) -> TagResult { - let tracks: Vec = if let Some(id) = track_id { + let mut stats = TagStats { + tracks_processed: 0, + tracks_matched: 0, + tracks_updated: 0, + tracks_skipped: 0, + tracks_errored: 0, + }; + + let tracks = if let Some(id) = track_id { vec![queries::tracks::get_by_id(conn, id).await?] } else { queries::tracks::get_needing_metadata(conn).await? }; - tracing::info!(count = tracks.len(), "tracks to process"); - let mut stats = TagStats::default(); - for track in &tracks { stats.tracks_processed += 1; - match tag_track(conn, provider, track, config).await { Ok(true) => { stats.tracks_matched += 1; @@ -229,11 +223,9 @@ pub async fn run_tagging( stats.tracks_updated += 1; } } - Ok(false) => { - stats.tracks_skipped += 1; - } + Ok(false) => stats.tracks_skipped += 1, Err(e) => { - tracing::error!(id = track.id, path = %track.file_path, "tagging error: {e}"); + tracing::error!(id = track.id, error = %e, "tagging failed"); stats.tracks_errored += 1; } }