97 lines
2.9 KiB
Rust
97 lines
2.9 KiB
Rust
use std::path::{Path, PathBuf};
|
|
|
|
use crate::agent::cover_variants;
|
|
use crate::scheduler::{Job, JobContext, JobLog};
|
|
|
|
pub struct CoverVariantBackfillJob;
|
|
|
|
#[async_trait::async_trait]
|
|
impl Job for CoverVariantBackfillJob {
|
|
fn name(&self) -> &'static str {
|
|
"cover_variant_backfill"
|
|
}
|
|
|
|
fn description(&self) -> &'static str {
|
|
"Generate missing resized cover image variants"
|
|
}
|
|
|
|
fn default_cron(&self) -> &'static str {
|
|
// Once a day after cover extraction and artist image assignment.
|
|
"0 45 3 * * *"
|
|
}
|
|
|
|
async fn run(&self, ctx: &JobContext, log: &mut JobLog) -> anyhow::Result<()> {
|
|
let storage_dir = &ctx.config.agent_storage_dir;
|
|
if storage_dir.is_empty() {
|
|
log.warn("agent_storage_dir is not configured, skipping cover variant backfill");
|
|
return Ok(());
|
|
}
|
|
|
|
let rows: Vec<(i64, String)> = sqlx::query_as(
|
|
"SELECT id, file_path FROM furumusic__media_file WHERE file_type = 'cover_art' ORDER BY id",
|
|
)
|
|
.fetch_all(&ctx.pool)
|
|
.await?;
|
|
|
|
if rows.is_empty() {
|
|
log.info("No cover art media files found");
|
|
return Ok(());
|
|
}
|
|
|
|
log.info(&format!(
|
|
"Found {} cover art media file(s), checking variants...",
|
|
rows.len()
|
|
));
|
|
|
|
let mut created = 0usize;
|
|
let mut unchanged = 0usize;
|
|
let mut missing_original = 0usize;
|
|
let mut failed = 0usize;
|
|
|
|
for (media_file_id, file_path) in rows {
|
|
let path = resolve_media_path(storage_dir, &file_path);
|
|
if !path.exists() {
|
|
missing_original += 1;
|
|
log.warn(&format!(
|
|
"Media file {media_file_id}: original cover not found at {}",
|
|
path.display()
|
|
));
|
|
continue;
|
|
}
|
|
|
|
match cover_variants::ensure_cover_variants(&path).await {
|
|
Ok(0) => unchanged += 1,
|
|
Ok(count) => {
|
|
created += count;
|
|
log.info(&format!(
|
|
"Media file {media_file_id}: created {count} variant(s)"
|
|
));
|
|
}
|
|
Err(err) => {
|
|
failed += 1;
|
|
log.warn(&format!(
|
|
"Media file {media_file_id}: failed to create variants: {err}"
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
log.info(&format!(
|
|
"Cover variant backfill complete: {created} variant(s) created, \
|
|
{unchanged} original(s) already complete, {missing_original} missing original(s), \
|
|
{failed} failed original(s)"
|
|
));
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn resolve_media_path(storage_dir: &str, file_path: &str) -> PathBuf {
|
|
let path = PathBuf::from(file_path);
|
|
if path.is_absolute() {
|
|
path
|
|
} else {
|
|
Path::new(storage_dir).join(path)
|
|
}
|
|
}
|