Skip to content

Commit

Permalink
Make network retries configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
kernitus committed Oct 29, 2023
1 parent dd33e06 commit 17c4e65
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 20 deletions.
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
13 changes: 7 additions & 6 deletions beetsplug/oldestdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
Recording = Dict[str, Any]
Work = Dict[str, Any]

MAX_RETRIES = 3
T = TypeVar('T')


class OldestDatePlugin(BeetsPlugin): # type: ignore
Expand All @@ -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']:
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 17c4e65

Please sign in to comment.