Skip to content

Commit

Permalink
chore: get rid of http_call_with_retry (#694)
Browse files Browse the repository at this point in the history
  • Loading branch information
jnussbaum committed Dec 19, 2023
1 parent 374b05a commit 70f6808
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 86 deletions.
8 changes: 4 additions & 4 deletions src/dsp_tools/commands/fast_xmlupload/process_files.py
Expand Up @@ -19,7 +19,7 @@

from dsp_tools.models.exceptions import UserError
from dsp_tools.utils.create_logger import get_logger
from dsp_tools.utils.shared import http_call_with_retry, make_chunks
from dsp_tools.utils.shared import make_chunks

logger = get_logger(__name__)
sipi_container: Optional[Container] = None
Expand All @@ -34,9 +34,9 @@ def _get_export_moving_image_frames_script() -> None:
user_folder.mkdir(parents=True, exist_ok=True)
global export_moving_image_frames_script
export_moving_image_frames_script = user_folder / "export-moving-image-frames.sh"
script_text_response = http_call_with_retry(
action=requests.get,
url="https://github.com/dasch-swiss/dsp-api/raw/main/sipi/scripts/export-moving-image-frames.sh",
script_text_response = requests.get(
"https://github.com/dasch-swiss/dsp-api/raw/main/sipi/scripts/export-moving-image-frames.sh",
timeout=30,
)
script_text = script_text_response.text
with open(export_moving_image_frames_script, "w", encoding="utf-8") as f:
Expand Down
34 changes: 12 additions & 22 deletions src/dsp_tools/commands/start_stack.py
Expand Up @@ -12,7 +12,6 @@

from dsp_tools.models.exceptions import UserError
from dsp_tools.utils.create_logger import get_logger
from dsp_tools.utils.shared import http_call_with_retry

logger = get_logger(__name__)

Expand Down Expand Up @@ -131,10 +130,7 @@ def _get_sipi_docker_config_lua(self) -> None:
Raises:
UserError: if max_file_size is set but cannot be injected into sipi.docker-config.lua
"""
docker_config_lua_response = http_call_with_retry(
action=requests.get,
url=f"{self.__url_prefix}sipi/config/sipi.docker-config.lua",
)
docker_config_lua_response = requests.get(f"{self.__url_prefix}sipi/config/sipi.docker-config.lua", timeout=30)
docker_config_lua_text = docker_config_lua_response.text
if self.__stack_configuration.max_file_size:
max_post_size_regex = r"max_post_size ?= ?[\'\"]?\d+[MG][\'\"]?"
Expand Down Expand Up @@ -173,11 +169,7 @@ def _wait_for_fuseki(self) -> None:
"""
for _ in range(6 * 60):
try:
response = http_call_with_retry(
action=requests.get,
url="http://0.0.0.0:3030/$/server",
auth=("admin", "test"),
)
response = requests.get("http://0.0.0.0:3030/$/server", auth=("admin", "test"), timeout=10)
if response.ok:
break
except Exception: # noqa: BLE001 (blind-except)
Expand All @@ -192,18 +184,17 @@ def _create_knora_test_repo(self) -> None:
Raises:
UserError: in case of failure
"""
repo_template_response = http_call_with_retry(
action=requests.get,
url=f"{self.__url_prefix}webapi/scripts/fuseki-repository-config.ttl.template",
repo_template_response = requests.get(
f"{self.__url_prefix}webapi/scripts/fuseki-repository-config.ttl.template",
timeout=30,
)
repo_template = repo_template_response.text
repo_template = repo_template.replace("@REPOSITORY@", "knora-test")
response = http_call_with_retry(
action=requests.post,
initial_timeout=10,
url="http://0.0.0.0:3030/$/datasets",
response = requests.post(
"http://0.0.0.0:3030/$/datasets",
files={"file": ("file.ttl", repo_template, "text/turtle; charset=utf8")},
auth=("admin", "test"),
timeout=30,
)
if not response.ok:
msg = (
Expand Down Expand Up @@ -235,18 +226,17 @@ def _load_data_into_repo(self) -> None:
("test_data/project_data/anything-data.ttl", "http://www.knora.org/data/0001/anything"),
]
for ttl_file, graph in ttl_files:
ttl_response = http_call_with_retry(action=requests.get, url=self.__url_prefix + ttl_file)
ttl_response = requests.get(self.__url_prefix + ttl_file, timeout=30)
if not ttl_response.ok:
msg = f"Cannot start DSP-API: Error when retrieving '{self.__url_prefix + ttl_file}'"
logger.error(f"{msg}'. response = {vars(ttl_response)}")
raise UserError(msg)
ttl_text = ttl_response.text
response = http_call_with_retry(
action=requests.post,
initial_timeout=10,
url=graph_prefix + graph,
response = requests.post(
graph_prefix + graph,
files={"file": ("file.ttl", ttl_text, "text/turtle; charset: utf-8")},
auth=("admin", "test"),
timeout=30,
)
if not response.ok:
logger.error(f"Cannot start DSP-API: Error when creating graph '{graph}'. response = {vars(response)}")
Expand Down
61 changes: 1 addition & 60 deletions src/dsp_tools/utils/shared.py
Expand Up @@ -4,18 +4,14 @@
import glob
import importlib.resources
import json
import time
import unicodedata
from datetime import datetime
from pathlib import Path
from typing import Any, Callable, Iterable, Optional, TypeGuard, TypeVar, Union, cast
from typing import Any, Iterable, Optional, TypeGuard, TypeVar, Union

import pandas as pd
import regex
import requests
from lxml import etree
from requests import ReadTimeout
from urllib3.exceptions import ReadTimeoutError

from dsp_tools.commands.excel2xml.propertyelement import PropertyElement
from dsp_tools.models.exceptions import BaseError, UserError
Expand Down Expand Up @@ -79,61 +75,6 @@ def login(
return con


def http_call_with_retry(
action: Callable[..., Any],
*args: Any,
initial_timeout: int = 10,
**kwargs: Any,
) -> requests.Response:
"""
Function that tries 7 times to execute an HTTP request.
Timeouts (and only timeouts) are catched, and the request is retried after a waiting time.
The waiting times are 1, 2, 4, 8, 16, 32, 64 seconds.
Every time, the previous timeout is increased by 10 seconds.
Use this only for actions that can be retried without side effects.
Args:
action: one of requests.get(), requests.post(), requests.put(), requests.delete()
initial_timeout: Timeout to start with. Defaults to 10 seconds.
*args: positional arguments for the action
**kwargs: keyword arguments for the action
Raises:
BaseError: if the action is not one of one of requests.get(), requests.post(), requests.put(), requests.delete()
Other Errors: errors from the requests library that are not timeouts
Returns:
response of the HTTP request
"""
if action not in (requests.get, requests.post, requests.put, requests.delete):
raise BaseError(
"This function can only be used with the methods get, post, put, and delete of the Python requests library."
)
action_as_str = f"{action=}, {args=}, {kwargs=}"
timeout = initial_timeout
for i in range(7):
try:
if args and not kwargs:
result = action(*args, timeout=timeout)
elif kwargs and not args:
result = action(**kwargs, timeout=timeout)
elif args and kwargs:
result = action(*args, **kwargs, timeout=timeout)
else:
result = action(timeout=timeout)
return cast(requests.Response, result)
except (TimeoutError, ReadTimeout, ReadTimeoutError):
timeout += 10
msg = f"Timeout Error: Retry request with timeout {timeout} in {2 ** i} seconds..."
print(f"{datetime.now()}: {msg}")
logger.error(f"{msg} {action_as_str} (retry-counter {i=:})", exc_info=True)
time.sleep(2**i)
continue

logger.error("Permanently unable to execute the API call. See logs for more details.")
raise BaseError("Permanently unable to execute the API call. See logs for more details.")


def validate_xml_against_schema(input_file: Union[str, Path, etree._ElementTree[Any]]) -> bool:
"""
Validates an XML file against the DSP XSD schema.
Expand Down

0 comments on commit 70f6808

Please sign in to comment.