fix: re-matching automatique des métadonnées externes après scan/import
Quand les métadonnées externes sont récupérées avant que les livres n'existent localement, le book_id reste NULL et les livres apparaissent comme "manquants" alors qu'ils sont présents. - Ajoute rematch_unlinked_books() qui associe les external_book_metadata non liées aux livres locaux par correspondance de volume - Appelé automatiquement à la fin de refresh_link() (API) - Appelé après chaque scan terminé dans l'indexer (job.rs) - Testé sur Dragon Ball : 47/85 external books rematched, 43 restants correspondent aux tomes Dragon Ball Z non présents localement Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,44 @@ use uuid::Uuid;
|
||||
|
||||
use crate::{analyzer, converter, scanner, AppState};
|
||||
|
||||
/// Re-match external_book_metadata with book_id IS NULL by volume number.
|
||||
async fn rematch_unlinked_books(pool: &PgPool, library_id: Uuid) {
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
UPDATE external_book_metadata ebm
|
||||
SET book_id = matched.book_id
|
||||
FROM (
|
||||
SELECT DISTINCT ON (ebm2.id)
|
||||
ebm2.id AS ebm_id,
|
||||
b.id AS book_id
|
||||
FROM external_book_metadata ebm2
|
||||
JOIN external_metadata_links eml ON eml.id = ebm2.link_id
|
||||
JOIN books b ON b.library_id = eml.library_id
|
||||
AND LOWER(COALESCE(NULLIF(b.series, ''), 'unclassified')) = LOWER(eml.series_name)
|
||||
AND b.volume = ebm2.volume_number
|
||||
WHERE eml.library_id = $1
|
||||
AND ebm2.book_id IS NULL
|
||||
AND ebm2.volume_number IS NOT NULL
|
||||
AND eml.status = 'approved'
|
||||
) matched
|
||||
WHERE ebm.id = matched.ebm_id
|
||||
"#,
|
||||
)
|
||||
.bind(library_id)
|
||||
.execute(pool)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(r) if r.rows_affected() > 0 => {
|
||||
info!("[METADATA] Re-matched {} unlinked external books for library {}", r.rows_affected(), library_id);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("[METADATA] Failed to rematch unlinked books: {e}");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn cleanup_stale_jobs(pool: &PgPool) -> Result<()> {
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
@@ -379,6 +417,12 @@ pub async fn process_job(
|
||||
|
||||
analyzer::analyze_library_books(state, job_id, target_library_id, false).await?;
|
||||
|
||||
// Re-match external book metadata that couldn't be linked during initial metadata fetch
|
||||
// (e.g., metadata was fetched before books were scanned)
|
||||
if let Some(lib_id) = target_library_id {
|
||||
rematch_unlinked_books(&state.pool, lib_id).await;
|
||||
}
|
||||
|
||||
sqlx::query(
|
||||
"UPDATE index_jobs SET status = 'success', finished_at = NOW(), progress_percent = 100, current_file = NULL WHERE id = $1",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user