fix(path-resolve): CWD-independent base dirs + quality-scan resolve diagnostic
The quality job still resolved 0/18 because the shared resolver kept relative
config paths ("./Transfer") as-is and gated them behind os.path.isdir("./Transfer"),
which only holds when the calling thread's CWD is the app root. The repair
worker thread's CWD isn't guaranteed to be /app, so base_dirs came back empty
and every track was "unresolved".
- _collect_base_dirs now also adds os.path.abspath() of every relative
candidate, so "./Transfer" → "/app/Transfer" regardless of CWD.
- quality_upgrade_scanner logs a one-shot [QualityResolve] diagnostic on the
first unresolved track (cwd, transfer_folder + abspath + isdir, base dirs
tried, abs-join existence) so any remaining mount mismatch is pinpointable
instead of a silent "all skipped".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5b3061ee2e
commit
973d28f61d
2 changed files with 49 additions and 2 deletions
|
|
@ -138,10 +138,25 @@ def _collect_base_dirs(
|
|||
except Exception as e:
|
||||
logger.debug("music paths read failed: %s", e)
|
||||
|
||||
# Normalize to absolute forms so resolution does NOT depend on the calling
|
||||
# thread's CWD. A relative config like "./Transfer" otherwise only resolves
|
||||
# when os.path.isdir("./Transfer") happens to be true from the current CWD —
|
||||
# which fails in background workers whose CWD isn't the app root, leaving
|
||||
# base_dirs empty and every track "unresolved". For each candidate we try
|
||||
# the raw form first (cheap, preserves an already-absolute path), then its
|
||||
# os.path.abspath() form so "./Transfer" → "/app/Transfer".
|
||||
expanded: list[str] = []
|
||||
for c in candidates:
|
||||
if not c:
|
||||
continue
|
||||
expanded.append(c)
|
||||
if not os.path.isabs(c):
|
||||
expanded.append(os.path.abspath(c))
|
||||
|
||||
# De-duplicate while preserving order, drop empties / non-existent dirs.
|
||||
seen: set[str] = set()
|
||||
out: list[str] = []
|
||||
for c in candidates:
|
||||
for c in expanded:
|
||||
if not c or c in seen:
|
||||
continue
|
||||
seen.add(c)
|
||||
|
|
|
|||
|
|
@ -85,14 +85,22 @@ class QualityUpgradeScannerJob(RepairJob):
|
|||
context.update_progress(0, total)
|
||||
|
||||
probe_failed = 0
|
||||
_diag_logged = False
|
||||
for i, (track_id, info) in enumerate(track_list):
|
||||
if context.check_stop():
|
||||
return result
|
||||
if i % 20 == 0 and context.wait_if_paused():
|
||||
return result
|
||||
|
||||
resolved = self._resolve_path(info.get('file_path', ''), context)
|
||||
raw_fp = info.get('file_path', '')
|
||||
resolved = self._resolve_path(raw_fp, context)
|
||||
if not resolved:
|
||||
# One-shot diagnostic on the first unresolved track — logs EXACTLY
|
||||
# what the resolver tried (base dirs, cwd) so a path/mount mismatch
|
||||
# is diagnosable instead of a silent "all skipped".
|
||||
if not _diag_logged:
|
||||
_diag_logged = True
|
||||
self._log_resolve_diag(raw_fp, context)
|
||||
result.skipped += 1
|
||||
probe_failed += 1
|
||||
continue
|
||||
|
|
@ -235,6 +243,30 @@ class QualityUpgradeScannerJob(RepairJob):
|
|||
config_manager=context.config_manager,
|
||||
)
|
||||
|
||||
def _log_resolve_diag(self, file_path, context):
|
||||
"""Log a detailed diagnostic for the first track whose path can't be
|
||||
resolved — the only reliable way to tell apart a CWD problem, a wrong
|
||||
transfer mount, or genuinely-missing files in this container."""
|
||||
from core.library.path_resolver import resolve_library_file_path_with_diagnostic
|
||||
try:
|
||||
_, attempt = resolve_library_file_path_with_diagnostic(
|
||||
file_path,
|
||||
transfer_folder=context.transfer_folder,
|
||||
config_manager=context.config_manager,
|
||||
)
|
||||
tf = context.transfer_folder
|
||||
abs_tf = os.path.abspath(tf) if tf else None
|
||||
logger.warning(
|
||||
"[QualityResolve] unresolved db_path=%r | cwd=%r | transfer_folder=%r "
|
||||
"(abspath=%r, isdir=%s) | base_dirs_tried=%r | abs_join_exists=%s",
|
||||
file_path, os.getcwd(), tf, abs_tf,
|
||||
os.path.isdir(abs_tf) if abs_tf else None,
|
||||
attempt.base_dirs_tried,
|
||||
os.path.exists(os.path.join(abs_tf, file_path)) if abs_tf else None,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning("[QualityResolve] diagnostic failed: %s", e)
|
||||
|
||||
def estimate_scope(self, context: JobContext) -> int:
|
||||
conn = None
|
||||
try:
|
||||
|
|
|
|||
Loading…
Reference in a new issue