Surface silent exceptions in watchlist + discovery + reorganize — 18 sites
- watchlist_scanner.py: 6 sites
- discovery/playlist.py: 5 sites
- discovery/sync.py: 4 sites
- watchlist/auto_scan.py: 1 site (1 left silent — finally-block scanner cleanup)
- library_reorganize.py: 2 sites (4 left silent — all in finally blocks:
conn.close, staging rmtree, sidecar delete, cleanup_empty_dir)
All non-finally sites converted to `logger.debug("...: %s", e)`.
Finally-block sites kept silent because logger calls during cleanup
(after exception was already raised) can themselves raise.
Refs #369
This commit is contained in:
parent
de348981a5
commit
8dc9f79f97
5 changed files with 36 additions and 36 deletions
|
|
@ -196,8 +196,8 @@ def run_playlist_discovery_worker(playlists, automation_id=None, deps: PlaylistD
|
||||||
current_item=track_name,
|
current_item=track_name,
|
||||||
log_line=f'{track_name} → {cached_match.get("name", "?")} (cache)', log_type='success')
|
log_line=f'{track_name} → {cached_match.get("name", "?")} (cache)', log_type='success')
|
||||||
continue
|
continue
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("discovery cache lookup failed: %s", e)
|
||||||
|
|
||||||
# Step 2: Generate search queries
|
# Step 2: Generate search queries
|
||||||
try:
|
try:
|
||||||
|
|
@ -252,8 +252,8 @@ def run_playlist_discovery_worker(playlists, automation_id=None, deps: PlaylistD
|
||||||
if match and confidence > best_confidence:
|
if match and confidence > best_confidence:
|
||||||
best_confidence = confidence
|
best_confidence = confidence
|
||||||
best_match = match
|
best_match = match
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("extended discovery search failed: %s", e)
|
||||||
|
|
||||||
# Step 4: Store results
|
# Step 4: Store results
|
||||||
if best_match and best_confidence >= min_confidence:
|
if best_match and best_confidence >= min_confidence:
|
||||||
|
|
@ -290,8 +290,8 @@ def run_playlist_discovery_worker(playlists, automation_id=None, deps: PlaylistD
|
||||||
if _raw:
|
if _raw:
|
||||||
track_number = _raw.get('track_number')
|
track_number = _raw.get('track_number')
|
||||||
disc_number = _raw.get('disc_number')
|
disc_number = _raw.get('disc_number')
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("metadata cache lookup for album enrichment failed: %s", e)
|
||||||
|
|
||||||
matched_data = {
|
matched_data = {
|
||||||
'id': best_match.id if hasattr(best_match, 'id') else '',
|
'id': best_match.id if hasattr(best_match, 'id') else '',
|
||||||
|
|
@ -323,8 +323,8 @@ def run_playlist_discovery_worker(playlists, automation_id=None, deps: PlaylistD
|
||||||
best_confidence, matched_data,
|
best_confidence, matched_data,
|
||||||
track_name, artist_name
|
track_name, artist_name
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("save discovery cache match failed: %s", e)
|
||||||
|
|
||||||
logger.info(f"[{i+1}/{len(undiscovered_tracks)}] {track_name} → {matched_data['name']} ({best_confidence:.2f})")
|
logger.info(f"[{i+1}/{len(undiscovered_tracks)}] {track_name} → {matched_data['name']} ({best_confidence:.2f})")
|
||||||
deps.update_automation_progress(automation_id,
|
deps.update_automation_progress(automation_id,
|
||||||
|
|
@ -366,8 +366,8 @@ def run_playlist_discovery_worker(playlists, automation_id=None, deps: PlaylistD
|
||||||
'failed_count': str(total_failed),
|
'failed_count': str(total_failed),
|
||||||
'skipped_count': str(total_skipped),
|
'skipped_count': str(total_skipped),
|
||||||
})
|
})
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("discovery_completed emit failed: %s", e)
|
||||||
|
|
||||||
logger.error(f"Playlist discovery complete: {total_discovered} discovered, {total_failed} failed, {total_skipped} skipped")
|
logger.error(f"Playlist discovery complete: {total_discovered} discovered, {total_failed} failed, {total_skipped} skipped")
|
||||||
deps.update_automation_progress(automation_id, status='finished', progress=100,
|
deps.update_automation_progress(automation_id, status='finished', progress=100,
|
||||||
|
|
|
||||||
|
|
@ -290,8 +290,8 @@ def run_sync_task(playlist_id, playlist_name, tracks_json, automation_id=None, p
|
||||||
logger.debug(f"Sync cache hit: '{original_title}' → server track {cached['server_track_id']}")
|
logger.debug(f"Sync cache hit: '{original_title}' → server track {cached['server_track_id']}")
|
||||||
return DatabaseTrackCached(db_track_check), cached['confidence']
|
return DatabaseTrackCached(db_track_check), cached['confidence']
|
||||||
logger.warning(f"Sync cache stale for '{original_title}' — track gone")
|
logger.warning(f"Sync cache stale for '{original_title}' — track gone")
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("sync match cache fast-path failed: %s", e)
|
||||||
# --- End cache fast-path ---
|
# --- End cache fast-path ---
|
||||||
|
|
||||||
# Try each artist (same logic as original)
|
# Try each artist (same logic as original)
|
||||||
|
|
@ -322,8 +322,8 @@ def run_sync_task(playlist_id, playlist_name, tracks_json, automation_id=None, p
|
||||||
spotify_id, me.clean_title(original_title), me.clean_artist(artist_name),
|
spotify_id, me.clean_title(original_title), me.clean_artist(artist_name),
|
||||||
active_server, db_track.id, db_track.title, confidence
|
active_server, db_track.id, db_track.title, confidence
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("save sync match cache failed: %s", e)
|
||||||
|
|
||||||
# Create mock track object for playlist creation
|
# Create mock track object for playlist creation
|
||||||
class DatabaseTrackMock:
|
class DatabaseTrackMock:
|
||||||
|
|
@ -429,8 +429,8 @@ def run_sync_task(playlist_id, playlist_name, tracks_json, automation_id=None, p
|
||||||
entry = db.get_sync_history_entry(_resync_entry_id)
|
entry = db.get_sync_history_entry(_resync_entry_id)
|
||||||
if entry:
|
if entry:
|
||||||
target_batch_id = entry.get('batch_id', sync_batch_id)
|
target_batch_id = entry.get('batch_id', sync_batch_id)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("resync history lookup failed: %s", e)
|
||||||
else:
|
else:
|
||||||
db.update_sync_history_completion(sync_batch_id, matched, synced, failed)
|
db.update_sync_history_completion(sync_batch_id, matched, synced, failed)
|
||||||
|
|
||||||
|
|
@ -466,8 +466,8 @@ def run_sync_task(playlist_id, playlist_name, tracks_json, automation_id=None, p
|
||||||
'synced_tracks': str(getattr(result, 'synced_tracks', 0)),
|
'synced_tracks': str(getattr(result, 'synced_tracks', 0)),
|
||||||
'failed_tracks': str(getattr(result, 'failed_tracks', 0)),
|
'failed_tracks': str(getattr(result, 'failed_tracks', 0)),
|
||||||
})
|
})
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("playlist_synced emit failed: %s", e)
|
||||||
|
|
||||||
# Save sync status with match counts and track hash for smart-skip on next scheduled sync
|
# Save sync status with match counts and track hash for smart-skip on next scheduled sync
|
||||||
import hashlib as _hl
|
import hashlib as _hl
|
||||||
|
|
|
||||||
|
|
@ -938,8 +938,8 @@ class _RunContext:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
self.on_progress(updates)
|
self.on_progress(updates)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("progress emit failed: %s", e)
|
||||||
|
|
||||||
def record_error(self, track_id, title, message, kind: str = 'skipped') -> None:
|
def record_error(self, track_id, title, message, kind: str = 'skipped') -> None:
|
||||||
with self.state_lock:
|
with self.state_lock:
|
||||||
|
|
@ -1185,8 +1185,8 @@ def reorganize_album(
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
on_progress(updates)
|
on_progress(updates)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("reorganize progress callback failed: %s", e)
|
||||||
|
|
||||||
# Load album + tracks
|
# Load album + tracks
|
||||||
album_data, tracks = load_album_and_tracks(db, album_id)
|
album_data, tracks = load_album_and_tracks(db, album_id)
|
||||||
|
|
|
||||||
|
|
@ -440,8 +440,8 @@ def process_watchlist_scan_automatically(automation_id=None, profile_id=None, de
|
||||||
'new_tracks_found': str(total_new_tracks),
|
'new_tracks_found': str(total_new_tracks),
|
||||||
'tracks_added': str(total_added_to_wishlist),
|
'tracks_added': str(total_added_to_wishlist),
|
||||||
})
|
})
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("watchlist_scan_completed emit failed: %s", e)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in automatic watchlist scan: {e}")
|
logger.error(f"Error in automatic watchlist scan: {e}")
|
||||||
|
|
|
||||||
|
|
@ -2745,8 +2745,8 @@ class WatchlistScanner:
|
||||||
if release_date_str and len(release_date_str) >= 10:
|
if release_date_str and len(release_date_str) >= 10:
|
||||||
release_date = datetime.strptime(release_date_str[:10], "%Y-%m-%d")
|
release_date = datetime.strptime(release_date_str[:10], "%Y-%m-%d")
|
||||||
is_new = (datetime.now() - release_date).days <= 30
|
is_new = (datetime.now() - release_date).days <= 30
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("album release_date parse failed: %s", e)
|
||||||
|
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
try:
|
try:
|
||||||
|
|
@ -2778,8 +2778,8 @@ class WatchlistScanner:
|
||||||
synth_pop += 15
|
synth_pop += 15
|
||||||
elif age_days <= 365:
|
elif age_days <= 365:
|
||||||
synth_pop += 5
|
synth_pop += 5
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("synthetic popularity age calc failed: %s", e)
|
||||||
if similar_artist.occurrence_count >= 3:
|
if similar_artist.occurrence_count >= 3:
|
||||||
synth_pop += 10
|
synth_pop += 10
|
||||||
elif similar_artist.occurrence_count >= 2:
|
elif similar_artist.occurrence_count >= 2:
|
||||||
|
|
@ -2902,8 +2902,8 @@ class WatchlistScanner:
|
||||||
if release_date_str and len(release_date_str) >= 10:
|
if release_date_str and len(release_date_str) >= 10:
|
||||||
release_date = datetime.strptime(release_date_str[:10], "%Y-%m-%d")
|
release_date = datetime.strptime(release_date_str[:10], "%Y-%m-%d")
|
||||||
is_new = (datetime.now() - release_date).days <= 30
|
is_new = (datetime.now() - release_date).days <= 30
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("album release_date parse failed: %s", e)
|
||||||
|
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
try:
|
try:
|
||||||
|
|
@ -3214,8 +3214,8 @@ class WatchlistScanner:
|
||||||
elif profile['avg_daily_plays'] > 20:
|
elif profile['avg_daily_plays'] > 20:
|
||||||
days_lookback = 21 # Heavy listener — keep it fresh
|
days_lookback = 21 # Heavy listener — keep it fresh
|
||||||
logger.info(f"Recent albums window: {days_lookback} days (avg {profile['avg_daily_plays']:.1f} plays/day)")
|
logger.info(f"Recent albums window: {days_lookback} days (avg {profile['avg_daily_plays']:.1f} plays/day)")
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("listening profile lookback adjust failed: %s", e)
|
||||||
cutoff_date = datetime.now() - timedelta(days=days_lookback)
|
cutoff_date = datetime.now() - timedelta(days=days_lookback)
|
||||||
discovery_sources = self._discovery_source_priority()
|
discovery_sources = self._discovery_source_priority()
|
||||||
if not discovery_sources:
|
if not discovery_sources:
|
||||||
|
|
@ -3498,8 +3498,8 @@ class WatchlistScanner:
|
||||||
_artist_genre_cache[_row[0].lower()] = {g.strip().lower() for g in _row[1].split(',') if g.strip()}
|
_artist_genre_cache[_row[0].lower()] = {g.strip().lower() for g in _row[1].split(',') if g.strip()}
|
||||||
_conn.close()
|
_conn.close()
|
||||||
logger.debug(f"Built genre cache for {len(_artist_genre_cache)} artists")
|
logger.debug(f"Built genre cache for {len(_artist_genre_cache)} artists")
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("artist genre cache build failed: %s", e)
|
||||||
|
|
||||||
logger.info(f"Curating playlists for sources: {sources_to_process}")
|
logger.info(f"Curating playlists for sources: {sources_to_process}")
|
||||||
|
|
||||||
|
|
@ -3760,8 +3760,8 @@ class WatchlistScanner:
|
||||||
_wa_list = self.database.get_watchlist_artists(profile_id=profile_id)
|
_wa_list = self.database.get_watchlist_artists(profile_id=profile_id)
|
||||||
for _wa in _wa_list:
|
for _wa in _wa_list:
|
||||||
_wa_id_to_name[str(_wa.id)] = (_wa.artist_name or '').lower()
|
_wa_id_to_name[str(_wa.id)] = (_wa.artist_name or '').lower()
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
logger.debug("watchlist artist id-to-name map failed: %s", e)
|
||||||
|
|
||||||
all_similar = self.database.get_top_similar_artists(limit=200, profile_id=profile_id)
|
all_similar = self.database.get_top_similar_artists(limit=200, profile_id=profile_id)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue