diff --git a/README.md b/README.md index 8cb7259..f836cee 100644 --- a/README.md +++ b/README.md @@ -12,21 +12,21 @@ necessary. The plugin is intended to be used in singleton mode. Undefined behavi # Configuration -| Key | Default Value | Description | -|:----------------------:|:-------------:| :-----:| -| auto | True | Run oldestdate during the import phase | -| ignore_track_id | False | During import, ignore existing track_id. Needed if using plugin on a library already tagged by MusicBrainz | -| filter_on_import | True | During import, weight down candidates with no work_id so you are more likely to choose a recording with a work_id | -| prompt_missing_work_id | True | During import, prompt to fix work_id if missing from chosen recording | -| force | False | Run even if `recording_` tags have already been applied to the track | -| overwrite_date | False | Overwrite the date MP3 tag field, inluding year, month, and day | -| overwrite_month | True | If overwriting date, also overwrite month field, otherwise leave blank | -| overwrite_day | True | If overwriting date, also overwrite day field, otherwise leave blank | -| filter_recordings | True | Skip recordings that have attributes before fetching them. This is usually live recordings | +| Key | Default Value | Description | +|:----------------------:|:-------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| auto | True | Run oldestdate during the import phase | +| ignore_track_id | False | During import, ignore existing track_id. Needed if using plugin on a library already tagged by MusicBrainz | +| filter_on_import | True | During import, weight down candidates with no work_id so you are more likely to choose a recording with a work_id | +| prompt_missing_work_id | True | During import, prompt to fix work_id if missing from chosen recording | +| force | False | Run even if `recording_` tags have already been applied to the track | +| overwrite_date | False | Overwrite the date MP3 tag field, inluding year, month, and day | +| overwrite_month | True | If overwriting date, also overwrite month field, otherwise leave blank | +| overwrite_day | True | If overwriting date, also overwrite day field, otherwise leave blank | +| filter_recordings | True | Skip recordings that have attributes before fetching them. This is usually live recordings | | approach | releases | What approach to use to find oldest date. Possible values: `recordings, releases, hybrid, both`. `recordings` works like `beets-recordingdate` did, `releases` is a far more accurate method. Hybrid only fetches releases if no date was found in recordings. | -| release_types | None | Filter releases by type, e.g. `['Official']`. Usually not needed | -| use_file_date | False | Use the file's embedded date too when looking for the oldest date | - +| release_types | None | Filter releases by type, e.g. `['Official']`. Usually not needed | +| use_file_date | False | Use the file's embedded date too when looking for the oldest date | +| max_network_retries | 3 | Maximum amount of times a given network call will be retried, using exponential backoff, before giving up. | ## Optimal Configuration diff --git a/beetsplug/oldestdate.py b/beetsplug/oldestdate.py index 4fb6db7..38de6ea 100644 --- a/beetsplug/oldestdate.py +++ b/beetsplug/oldestdate.py @@ -21,8 +21,6 @@ Recording = Dict[str, Any] Work = Dict[str, Any] -MAX_RETRIES = 3 -T = TypeVar('T') class OldestDatePlugin(BeetsPlugin): # type: ignore @@ -44,7 +42,8 @@ def __init__(self) -> None: 'filter_recordings': True, # Skip recordings with attributes before fetching them 'approach': 'releases', # recordings, releases, hybrid, both 'release_types': None, # Filter by release type, e.g. ['Official'] - 'use_file_date': False # Also use file's embedded date when looking for oldest date + 'use_file_date': False, # Also use file's embedded date when looking for oldest date + 'max_network_retries': 3 # Maximum amount of times a given network call will be retried }) if self.config['auto']: @@ -128,14 +127,16 @@ def _import_task_choice(self, task: ImportTask, session: ImportSession) -> None: task.choice_flag = action.SKIP return + T = TypeVar('T') def _retry_on_network_error(self, func: Callable[..., T], *args: Any, **kwargs: Any) -> T: - for attempt in range(MAX_RETRIES): + max_retries: int = self.config['max_network_retries'].get() + for attempt in range(max_retries): try: return func(*args, **kwargs) except NetworkError: - if attempt < MAX_RETRIES - 1: # No need to wait after the last attempt + if attempt < max_retries - 1: # No need to wait after the last attempt delay: int = 2 ** attempt - self._log.info(f'Network call failed, attempt {attempt}/{MAX_RETRIES}. Trying again in {delay}') + self._log.info(f'Network call failed, attempt {attempt}/{max_retries}. Trying again in {delay}') time.sleep(delay) # Exponential backoff each attempt else: raise