From 4946ff0d03512233d11ccae475e70964976c399e Mon Sep 17 00:00:00 2001 From: Antti Kettunen Date: Sat, 11 Apr 2026 14:01:49 +0300 Subject: [PATCH 1/2] Remove redundant repetition of lookback period change during watchlist scan Unnecessary noise on the logs --- core/watchlist_scanner.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/core/watchlist_scanner.py b/core/watchlist_scanner.py index bb57e6e5..0f09fc8f 100644 --- a/core/watchlist_scanner.py +++ b/core/watchlist_scanner.py @@ -353,6 +353,7 @@ class WatchlistScanner: self._database = None self._wishlist_service = None self._matching_engine = None + self._rescan_cutoff_log_marker = None if metadata_service: self._metadata_service = metadata_service @@ -932,7 +933,9 @@ class WatchlistScanner: # Check if a lookback period change requires a one-time wider window rescan_cutoff = self._get_rescan_cutoff() if rescan_cutoff == 'all': - logger.info(f"Lookback period changed to 'all' — returning full discography") + if self._rescan_cutoff_log_marker != 'all': + logger.info(f"Lookback period changed to 'all' — returning full discography") + self._rescan_cutoff_log_marker = 'all' cutoff_timestamp = None needs_full_discog = True elif rescan_cutoff is not None: @@ -942,7 +945,10 @@ class WatchlistScanner: if rescan_cutoff.tzinfo is None: rescan_cutoff = rescan_cutoff.replace(tzinfo=timezone.utc) if rescan_cutoff < scan_ts: - logger.info(f"Lookback period change detected — expanding cutoff from {cutoff_timestamp} to {rescan_cutoff}") + marker = rescan_cutoff.isoformat() + if self._rescan_cutoff_log_marker != marker: + logger.info(f"Lookback period change detected — expanding cutoff from {cutoff_timestamp} to {rescan_cutoff}") + self._rescan_cutoff_log_marker = marker cutoff_timestamp = rescan_cutoff else: # No scan timestamp — first scan, use lookback period @@ -1248,6 +1254,7 @@ class WatchlistScanner: cursor.execute("DELETE FROM metadata WHERE key = 'watchlist_rescan_cutoff'") conn.commit() logger.info("Cleared watchlist rescan cutoff flag") + self._rescan_cutoff_log_marker = None except Exception as e: logger.debug(f"Error clearing rescan cutoff: {e}") @@ -3266,4 +3273,4 @@ def get_watchlist_scanner(spotify_client: SpotifyClient) -> WatchlistScanner: global _watchlist_scanner_instance if _watchlist_scanner_instance is None: _watchlist_scanner_instance = WatchlistScanner(spotify_client) - return _watchlist_scanner_instance \ No newline at end of file + return _watchlist_scanner_instance From 337ec7309b12423c01e4136650c4a744c49bc6ca Mon Sep 17 00:00:00 2001 From: Antti Kettunen Date: Sat, 11 Apr 2026 14:35:58 +0300 Subject: [PATCH 2/2] Initialize the database only once per process Since MusicDatabase is initialized per-thread (which I don't dare to change), we end up needlessly calling _initialize_database for each client that gets created, thus making a ton of redundant db initialization / migration calls over and over again throughout the process' lifetime --- database/music_database.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/database/music_database.py b/database/music_database.py index fe6cbb2f..23444547 100644 --- a/database/music_database.py +++ b/database/music_database.py @@ -15,6 +15,9 @@ from utils.logging_config import get_logger logger = get_logger("music_database") +_database_initialized_paths = set() +_database_initialization_lock = threading.Lock() + # Import matching engine for enhanced similarity logic try: from core.matching_engine import MusicMatchingEngine @@ -168,8 +171,19 @@ class MusicDatabase: self.database_path = Path(database_path) self.database_path.parent.mkdir(parents=True, exist_ok=True) - # Initialize database - self._initialize_database() + # Initialize database once per process for this path + self._initialize_database_once() + + def _initialize_database_once(self): + """Run schema setup and migrations once per database path per process.""" + db_key = str(self.database_path.resolve()) + + with _database_initialization_lock: + if db_key in _database_initialized_paths: + return + + self._initialize_database() + _database_initialized_paths.add(db_key) def _get_connection(self) -> sqlite3.Connection: """Get a NEW database connection for each operation (thread-safe)""" @@ -10796,4 +10810,4 @@ def close_database(): except Exception as e: # Ignore threading errors during shutdown pass - _database_instances.clear() \ No newline at end of file + _database_instances.clear()