refactor: Make rate limiting configurable and move session validation to Tidal class
- Add api_rate_limit_batch_size and api_rate_limit_delay_sec to Settings (cfg.py) - Move validate_session() and is_authentication_error() to Tidal class (config.py) - Update _load_albums_with_rate_limiting() to use config values instead of hardcoded 20/3 - Update _handle_album_load_error() to use Tidal.is_authentication_error() - Remove _validate_session() from gui.py (now uses Tidal.validate_session()) - Addresses maintainer feedback: configurable tweaking variables and proper separation of concerns
This commit is contained in:
@@ -190,6 +190,26 @@ class Tidal(BaseConfig, metaclass=SingletonMeta):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def validate_session(self) -> bool:
|
||||||
|
"""Validate that the TIDAL session is still authenticated.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if session is valid, False otherwise.
|
||||||
|
"""
|
||||||
|
return self.session.check_login()
|
||||||
|
|
||||||
|
def is_authentication_error(self, error: Exception) -> bool:
|
||||||
|
"""Check if an error is related to authentication/OAuth issues.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
error (Exception): The exception to check.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the error is authentication-related, False otherwise.
|
||||||
|
"""
|
||||||
|
error_msg = str(error)
|
||||||
|
return "401" in error_msg or "OAuth" in error_msg or "token" in error_msg.lower()
|
||||||
|
|
||||||
|
|
||||||
class HandlingApp(metaclass=SingletonMeta):
|
class HandlingApp(metaclass=SingletonMeta):
|
||||||
event_abort: Event = Event()
|
event_abort: Event = Event()
|
||||||
|
|||||||
+12
-21
@@ -728,16 +728,19 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
dict[int, Album]: Dictionary of successfully loaded full album objects.
|
dict[int, Album]: Dictionary of successfully loaded full album objects.
|
||||||
"""
|
"""
|
||||||
albums_dict = {}
|
albums_dict = {}
|
||||||
|
batch_size = self.settings.data.api_rate_limit_batch_size
|
||||||
|
delay_sec = self.settings.data.api_rate_limit_delay_sec
|
||||||
|
|
||||||
for idx, album_id in enumerate(album_ids.keys(), start=1):
|
for idx, album_id in enumerate(album_ids.keys(), start=1):
|
||||||
try:
|
try:
|
||||||
# Add delay every 20 albums to avoid rate limiting
|
# Add delay every N albums to avoid rate limiting
|
||||||
if idx > 1 and (idx - 1) % 20 == 0:
|
if idx > 1 and (idx - 1) % batch_size == 0:
|
||||||
logger_gui.info(f"🛑 RATE LIMITING: Processed {idx - 1} albums, pausing for 3 seconds...")
|
logger_gui.info(f"🛑 RATE LIMITING: Processed {idx - 1} albums, pausing for {delay_sec} seconds...")
|
||||||
time.sleep(3)
|
time.sleep(delay_sec)
|
||||||
|
|
||||||
# Check session validity before making API calls
|
# Check session validity before making API calls
|
||||||
if not self._validate_session():
|
if not self.tidal.validate_session():
|
||||||
|
logger_gui.error("Session expired. Please restart the application and login again.")
|
||||||
return albums_dict
|
return albums_dict
|
||||||
|
|
||||||
# Reload full album object
|
# Reload full album object
|
||||||
@@ -753,17 +756,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
logger_gui.info(f"Successfully loaded {len(albums_dict)} albums.")
|
logger_gui.info(f"Successfully loaded {len(albums_dict)} albums.")
|
||||||
return albums_dict
|
return albums_dict
|
||||||
|
|
||||||
def _validate_session(self) -> bool:
|
|
||||||
"""Validate that the TIDAL session is still authenticated.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if session is valid, False otherwise.
|
|
||||||
"""
|
|
||||||
if not self.tidal.session.check_login():
|
|
||||||
logger_gui.error("Session expired. Please restart the application and login again.")
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _handle_album_load_error(self, error: Exception, album_id: int) -> bool:
|
def _handle_album_load_error(self, error: Exception, album_id: int) -> bool:
|
||||||
"""Handle errors that occur when loading an album.
|
"""Handle errors that occur when loading an album.
|
||||||
|
|
||||||
@@ -774,10 +766,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True if processing should continue, False if it should stop.
|
bool: True if processing should continue, False if it should stop.
|
||||||
"""
|
"""
|
||||||
error_msg = str(error)
|
# Check for OAuth/authentication errors using Tidal class method
|
||||||
|
if self.tidal.is_authentication_error(error):
|
||||||
# Check for OAuth/authentication errors
|
error_msg = str(error)
|
||||||
if "401" in error_msg or "OAuth" in error_msg or "token" in error_msg.lower():
|
|
||||||
logger_gui.error(f"Authentication error: {error_msg}")
|
logger_gui.error(f"Authentication error: {error_msg}")
|
||||||
logger_gui.error("Your session has expired. Please restart the application and login again.")
|
logger_gui.error("Your session has expired. Please restart the application and login again.")
|
||||||
self.s_statusbar_message.emit(
|
self.s_statusbar_message.emit(
|
||||||
@@ -785,7 +776,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger_gui.warning(f"Failed to load album {album_id}: {error_msg}")
|
logger_gui.warning(f"Failed to load album {album_id}: {error!s}")
|
||||||
logger_gui.info(
|
logger_gui.info(
|
||||||
"Note: Some albums may be unavailable due to region restrictions or removal from TIDAL. This is normal."
|
"Note: Some albums may be unavailable due to region restrictions or removal from TIDAL. This is normal."
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ class Settings:
|
|||||||
filename_delimiter_artist: str = ", "
|
filename_delimiter_artist: str = ", "
|
||||||
filename_delimiter_album_artist: str = ", "
|
filename_delimiter_album_artist: str = ", "
|
||||||
metadata_target_upc: MetadataTargetUPC = MetadataTargetUPC.UPC
|
metadata_target_upc: MetadataTargetUPC = MetadataTargetUPC.UPC
|
||||||
|
# Rate limiting for API calls (tweaking variables)
|
||||||
|
api_rate_limit_batch_size: int = 20 # Number of albums to process before applying rate limit delay
|
||||||
|
api_rate_limit_delay_sec: float = 3.0 # Delay in seconds between batches to avoid rate limiting
|
||||||
|
|
||||||
|
|
||||||
@dataclass_json
|
@dataclass_json
|
||||||
@@ -127,6 +130,8 @@ class HelpSettings:
|
|||||||
metadata_target_upc: str = (
|
metadata_target_upc: str = (
|
||||||
"Select the target metadata tag ('UPC', 'BARCODE', 'EAN') where to write the UPC information to. Default: 'UPC'."
|
"Select the target metadata tag ('UPC', 'BARCODE', 'EAN') where to write the UPC information to. Default: 'UPC'."
|
||||||
)
|
)
|
||||||
|
api_rate_limit_batch_size: str = "Number of albums to process before applying rate limit delay (tweaking variable)."
|
||||||
|
api_rate_limit_delay_sec: str = "Delay in seconds between batches to avoid API rate limiting (tweaking variable)."
|
||||||
|
|
||||||
|
|
||||||
@dataclass_json
|
@dataclass_json
|
||||||
|
|||||||
Reference in New Issue
Block a user