diff --git a/sources/bin/shared.py b/sources/bin/shared.py index 21c9c108..ac7cbe8c 100644 --- a/sources/bin/shared.py +++ b/sources/bin/shared.py @@ -90,23 +90,39 @@ def read_suite_per_tool_id(tool_fp: str) -> Dict: return tools -def get_request_json(url: str, headers: dict) -> dict: - """ - Return JSON output using request - - :param url: galaxy tool id - """ - - try: - r = requests.get(url, auth=None, headers=headers) - r.raise_for_status() # Optional: Raises an HTTPError if the response was an unsuccessful status code - except ConnectionError as e: - raise ConnectionError("Connection aborted: Remote end closed connection without response") from e - except requests.exceptions.RequestException as e: - # This will handle other possible errors (e.g., timeout, HTTPError) - raise SystemExit(e) - else: - return r.json() +def get_request_json(url: str, headers: dict, retries: int = 3, delay: float = 2.0) -> dict: + """ + Perform a GET request to retrieve JSON output from a specified URL, with retry on ConnectionError. + + :param url: URL to send the GET request to. + :param headers: Headers to include in the GET request. + :param retries: Number of retry attempts in case of a ConnectionError (default is 3). + :param delay: Delay in seconds between retries (default is 2.0 seconds). + :return: JSON response as a dictionary. + :raises ConnectionError: If all retry attempts fail due to a connection error. + :raises SystemExit: For any other request-related errors. + """ + attempt = 0 # Track the number of attempts + + while attempt < retries: + try: + r = requests.get(url, auth=None, headers=headers) + r.raise_for_status() # Raises an HTTPError for unsuccessful status codes + return r.json() # Attempt to parse JSON response if successful + except ConnectionError as e: + attempt += 1 + if attempt == retries: + raise ConnectionError( + "Connection aborted after multiple retries: Remote end closed connection without response" + ) from e + print(f"Connection error on attempt {attempt}/{retries}. Retrying in {delay} seconds...") + time.sleep(delay) # Wait before retrying + except requests.exceptions.RequestException as e: + # Handles all other exceptions from the requests library + raise SystemExit(f"Request failed: {e}") + except ValueError as e: + # Handles cases where the response isn't valid JSON + raise ValueError("Response content is not valid JSON") from e def format_date(date: str) -> str: