From d72664261fa8c8114246557b2a5083d830477be2 Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Mon, 7 Aug 2023 11:17:50 +0200 Subject: [PATCH 1/4] edit --- src/dsp_tools/fast_xmlupload/process_files.py | 9 ++++-- src/dsp_tools/fast_xmlupload/upload_files.py | 7 +++-- src/dsp_tools/utils/shared.py | 30 ++++++++++++++++++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/dsp_tools/fast_xmlupload/process_files.py b/src/dsp_tools/fast_xmlupload/process_files.py index 1d7e37a1bc..c2735f1ab0 100644 --- a/src/dsp_tools/fast_xmlupload/process_files.py +++ b/src/dsp_tools/fast_xmlupload/process_files.py @@ -20,6 +20,8 @@ from dsp_tools.models.exceptions import UserError from dsp_tools.utils.logging import get_logger +from dsp_tools.utils.shared import catch_timeout_of_request + logger = get_logger(__name__, filesize_mb=100, backupcount=36) sipi_container: Optional[Container] = None export_moving_image_frames_script: Optional[Path] = None @@ -33,10 +35,11 @@ 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 = requests.get( + script_text_response = catch_timeout_of_request( + requests.get, "https://github.com/dasch-swiss/dsp-api/raw/main/sipi/scripts/export-moving-image-frames.sh", - timeout=10, - ).text + ) + script_text = script_text_response.text with open(export_moving_image_frames_script, "w", encoding="utf-8") as f: f.write(script_text) diff --git a/src/dsp_tools/fast_xmlupload/upload_files.py b/src/dsp_tools/fast_xmlupload/upload_files.py index fe6f227bad..c5c3c43c81 100644 --- a/src/dsp_tools/fast_xmlupload/upload_files.py +++ b/src/dsp_tools/fast_xmlupload/upload_files.py @@ -11,7 +11,7 @@ from dsp_tools.models.connection import Connection from dsp_tools.models.exceptions import BaseError from dsp_tools.utils.logging import get_logger -from dsp_tools.utils.shared import login +from dsp_tools.utils.shared import catch_timeout_of_request, login logger = get_logger(__name__) @@ -110,11 +110,12 @@ def _upload_without_processing( try: with open(file, "rb") as bitstream: try: - response_upload = requests.post( + response_upload = catch_timeout_of_request( + requests.post, + initial_timeout=8 * 60, url=f"{regex.sub(r'/$', '', sipi_url)}/upload_without_processing", headers={"Authorization": f"Bearer {con.get_token()}"}, files={"file": bitstream}, - timeout=8 * 60, ) except Exception: # pylint: disable=broad-exception-caught err_msg = f"An exception was raised while calling the /upload_without_processing route for {file}" diff --git a/src/dsp_tools/utils/shared.py b/src/dsp_tools/utils/shared.py index 80d54d10df..699e252b80 100644 --- a/src/dsp_tools/utils/shared.py +++ b/src/dsp_tools/utils/shared.py @@ -13,6 +13,7 @@ import regex from lxml import etree from requests import ReadTimeout, RequestException +from urllib3.exceptions import ReadTimeoutError from dsp_tools.models.connection import Connection from dsp_tools.models.exceptions import BaseError, UserError @@ -52,6 +53,33 @@ def login( return con +def catch_timeout_of_request( + action: Callable[..., Any], + *args: Any, + initial_timeout: int = 10, + **kwargs: Any, +) -> Any: + action_as_str = f"action='{action}', args='{args}', kwargs='{kwargs}'" + timeout = initial_timeout + for i in range(7): + try: + if args and not kwargs: + return action(*args, timeout=timeout) + elif kwargs and not args: + return action(**kwargs, timeout=timeout) + elif args and kwargs: + return action(*args, **kwargs, timeout=timeout) + else: + return action(timeout=timeout) + except (TimeoutError, ReadTimeout, ReadTimeoutError): + timeout += 10 + msg = f"Timeout Error: Retry request with timeout {timeout} in {2 ** i} seconds..." + print(f"{datetime.now().isoformat()}: {msg}") + logger.error(f"{msg} {action_as_str} (retry-counter i={i})", exc_info=True) + time.sleep(2**i) + continue + + def try_network_action( action: Callable[..., Any], *args: Any, @@ -59,7 +87,7 @@ def try_network_action( ) -> Any: """ Helper method that tries 7 times to execute an action. - If a ConnectionError, a requests.exceptions.RequestException, or a non-permanent BaseError occors, + If a timeout error, a ConnectionError, a requests.exceptions.RequestException, or a non-permanent BaseError occors, it waits and retries. The waiting times are 1, 2, 4, 8, 16, 32, 64 seconds. If another exception occurs, it escalates. From 0904bebcc9660a6f2925054d6b7ffa77ba454240 Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Mon, 7 Aug 2023 13:43:38 +0200 Subject: [PATCH 2/4] edit --- src/dsp_tools/fast_xmlupload/process_files.py | 8 ++-- src/dsp_tools/fast_xmlupload/upload_files.py | 6 +-- src/dsp_tools/models/connection.py | 20 ++++----- src/dsp_tools/models/sipi.py | 9 ++-- src/dsp_tools/utils/shared.py | 20 ++++++++- src/dsp_tools/utils/stack_handling.py | 41 ++++++++++++------- 6 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/dsp_tools/fast_xmlupload/process_files.py b/src/dsp_tools/fast_xmlupload/process_files.py index c2735f1ab0..3fc2f5ad0e 100644 --- a/src/dsp_tools/fast_xmlupload/process_files.py +++ b/src/dsp_tools/fast_xmlupload/process_files.py @@ -20,7 +20,7 @@ from dsp_tools.models.exceptions import UserError from dsp_tools.utils.logging import get_logger -from dsp_tools.utils.shared import catch_timeout_of_request +from dsp_tools.utils.shared import try_api_call logger = get_logger(__name__, filesize_mb=100, backupcount=36) sipi_container: Optional[Container] = None @@ -35,9 +35,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 = catch_timeout_of_request( - requests.get, - "https://github.com/dasch-swiss/dsp-api/raw/main/sipi/scripts/export-moving-image-frames.sh", + script_text_response = try_api_call( + action=requests.get, + url="https://github.com/dasch-swiss/dsp-api/raw/main/sipi/scripts/export-moving-image-frames.sh", ) script_text = script_text_response.text with open(export_moving_image_frames_script, "w", encoding="utf-8") as f: diff --git a/src/dsp_tools/fast_xmlupload/upload_files.py b/src/dsp_tools/fast_xmlupload/upload_files.py index c5c3c43c81..3fc1f1dbb0 100644 --- a/src/dsp_tools/fast_xmlupload/upload_files.py +++ b/src/dsp_tools/fast_xmlupload/upload_files.py @@ -11,7 +11,7 @@ from dsp_tools.models.connection import Connection from dsp_tools.models.exceptions import BaseError from dsp_tools.utils.logging import get_logger -from dsp_tools.utils.shared import catch_timeout_of_request, login +from dsp_tools.utils.shared import try_api_call, login logger = get_logger(__name__) @@ -110,8 +110,8 @@ def _upload_without_processing( try: with open(file, "rb") as bitstream: try: - response_upload = catch_timeout_of_request( - requests.post, + response_upload = try_api_call( + action=requests.post, initial_timeout=8 * 60, url=f"{regex.sub(r'/$', '', sipi_url)}/upload_without_processing", headers={"Authorization": f"Bearer {con.get_token()}"}, diff --git a/src/dsp_tools/models/connection.py b/src/dsp_tools/models/connection.py index e62d8a28c6..fc7ff5c84c 100644 --- a/src/dsp_tools/models/connection.py +++ b/src/dsp_tools/models/connection.py @@ -68,7 +68,7 @@ def login(self, email: str, password: str) -> None: self._server + "/v2/authentication", headers={"Content-Type": "application/json; charset=UTF-8"}, data=jsondata, - timeout=10, + timeout=20, ) check_for_api_error(response) result = response.json() @@ -105,7 +105,7 @@ def logout(self) -> None: response = requests.delete( self._server + "/v2/authentication", headers={"Authorization": "Bearer " + self._token}, - timeout=10, + timeout=20, ) check_for_api_error(response) self._token = None @@ -192,19 +192,19 @@ def get(self, path: str, headers: Optional[dict[str, str]] = None) -> dict[str, path = "/" + path if not self._token: if not headers: - response = requests.get(self._server + path, timeout=10) + response = requests.get(self._server + path, timeout=20) else: - response = requests.get(self._server + path, headers, timeout=10) + response = requests.get(self._server + path, headers, timeout=20) else: if not headers: response = requests.get( self._server + path, headers={"Authorization": "Bearer " + self._token}, - timeout=10, + timeout=20, ) else: headers["Authorization"] = "Bearer " + self._token - response = requests.get(self._server + path, headers, timeout=10) + response = requests.get(self._server + path, headers, timeout=20) check_for_api_error(response) json_response = response.json() @@ -225,14 +225,14 @@ def put(self, path: str, jsondata: Optional[str] = None, content_type: str = "ap response = requests.put( self._server + path, headers={"Authorization": "Bearer " + self._token}, - timeout=10, + timeout=20, ) else: response = requests.put( self._server + path, headers={"Content-Type": content_type + "; charset=UTF-8", "Authorization": "Bearer " + self._token}, data=jsondata, - timeout=10, + timeout=20, ) check_for_api_error(response) result = response.json() @@ -252,14 +252,14 @@ def delete(self, path: str, params: Optional[any] = None): self._server + path, headers={"Authorization": "Bearer " + self._token}, params=params, - timeout=10, + timeout=20, ) else: response = requests.delete( self._server + path, headers={"Authorization": "Bearer " + self._token}, - timeout=10, + timeout=20, ) check_for_api_error(response) result = response.json() diff --git a/src/dsp_tools/models/sipi.py b/src/dsp_tools/models/sipi.py index 6bbf1f58ca..a34c36945c 100644 --- a/src/dsp_tools/models/sipi.py +++ b/src/dsp_tools/models/sipi.py @@ -7,6 +7,8 @@ from dsp_tools.models.connection import check_for_api_error +from dsp_tools.utils.shared import try_api_call + class Sipi: """Represents the Sipi instance""" @@ -29,11 +31,12 @@ def upload_bitstream(self, filepath: str) -> dict[Any, Any]: files = { "file": (os.path.basename(filepath), bitstream_file), } - response = requests.post( - self.sipi_server + "/upload", + response = try_api_call( + action=requests.post, + initial_timeout=5 * 60, + url=self.sipi_server + "/upload", headers={"Authorization": "Bearer " + self.token}, files=files, - timeout=5 * 60, ) check_for_api_error(response) res: dict[Any, Any] = response.json() diff --git a/src/dsp_tools/utils/shared.py b/src/dsp_tools/utils/shared.py index 699e252b80..820d86ee46 100644 --- a/src/dsp_tools/utils/shared.py +++ b/src/dsp_tools/utils/shared.py @@ -13,6 +13,7 @@ import regex from lxml import etree from requests import ReadTimeout, RequestException +import requests from urllib3.exceptions import ReadTimeoutError from dsp_tools.models.connection import Connection @@ -53,12 +54,26 @@ def login( return con -def catch_timeout_of_request( +def try_api_call( action: Callable[..., Any], *args: Any, initial_timeout: int = 10, **kwargs: Any, ) -> Any: + """ + Function that tries 7 times to execute an API call. + 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. + + Returns: + _description_ + """ + 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 requests.") action_as_str = f"action='{action}', args='{args}', kwargs='{kwargs}'" timeout = initial_timeout for i in range(7): @@ -79,6 +94,9 @@ def catch_timeout_of_request( 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 try_network_action( action: Callable[..., Any], diff --git a/src/dsp_tools/utils/stack_handling.py b/src/dsp_tools/utils/stack_handling.py index 8e43aead14..2349f18dca 100644 --- a/src/dsp_tools/utils/stack_handling.py +++ b/src/dsp_tools/utils/stack_handling.py @@ -13,6 +13,8 @@ from dsp_tools.models.exceptions import UserError from dsp_tools.utils.logging import get_logger +from dsp_tools.utils.shared import try_api_call + logger = get_logger(__name__) @@ -121,7 +123,11 @@ 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_text = requests.get(f"{self.__url_prefix}sipi/config/sipi.docker-config.lua", timeout=10).text + docker_config_lua_response = try_api_call( + action=get, + url=f"{self.__url_prefix}sipi/config/sipi.docker-config.lua", + ) + 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+M[\'\"]" if not re.search(max_post_size_regex, docker_config_lua_text): @@ -159,7 +165,11 @@ def _wait_for_fuseki(self) -> None: """ for _ in range(6 * 60): try: - response = requests.get(url="http://0.0.0.0:3030/$/server", auth=("admin", "test"), timeout=10) + response = try_api_call( + action=requests.get, + url="http://0.0.0.0:3030/$/server", + auth=("admin", "test"), + ) if response.ok: break except Exception: # pylint: disable=broad-exception-caught @@ -174,16 +184,18 @@ def _create_knora_test_repo(self) -> None: Raises: UserError: in case of failure """ - repo_template = requests.get( - f"{self.__url_prefix}webapi/scripts/fuseki-repository-config.ttl.template", - timeout=10, - ).text + repo_template_response = try_api_call( + action=requests.get, + url=f"{self.__url_prefix}webapi/scripts/fuseki-repository-config.ttl.template", + ) + repo_template = repo_template_response.text repo_template = repo_template.replace("@REPOSITORY@", "knora-test") - response = requests.post( + response = try_api_call( + action=requests.post, + initial_timeout=10, url="http://0.0.0.0:3030/$/datasets", files={"file": ("file.ttl", repo_template, "text/turtle; charset=utf8")}, auth=("admin", "test"), - timeout=10, ) if not response.ok: msg = ( @@ -215,17 +227,18 @@ 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_text_response = requests.get(self.__url_prefix + ttl_file, timeout=10) - if not ttl_text_response.ok: + ttl_response = try_api_call(action=requests.get, url=self.__url_prefix + ttl_file) + 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_text_response)}") + logger.error(f"{msg}'. response = {vars(ttl_response)}") raise UserError(msg) - ttl_text = ttl_text_response.text - response = requests.post( + ttl_text = ttl_response.text + response = try_api_call( + action=requests.post, + initial_timeout=10, url=graph_prefix + graph, files={"file": ("file.ttl", ttl_text, "text/turtle; charset: utf-8")}, auth=("admin", "test"), - timeout=10, ) if not response.ok: logger.error(f"Cannot start DSP-API: Error when creating graph '{graph}'. response = {vars(response)}") From 7f31583165b7f19b2618bd080a5c641d8d6a661f Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Mon, 7 Aug 2023 14:38:01 +0200 Subject: [PATCH 3/4] fix --- src/dsp_tools/utils/stack_handling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dsp_tools/utils/stack_handling.py b/src/dsp_tools/utils/stack_handling.py index 2349f18dca..3e080e373b 100644 --- a/src/dsp_tools/utils/stack_handling.py +++ b/src/dsp_tools/utils/stack_handling.py @@ -124,7 +124,7 @@ def _get_sipi_docker_config_lua(self) -> None: UserError: if max_file_size is set but cannot be injected into sipi.docker-config.lua """ docker_config_lua_response = try_api_call( - action=get, + action=requests.get, url=f"{self.__url_prefix}sipi/config/sipi.docker-config.lua", ) docker_config_lua_text = docker_config_lua_response.text From cb1b6aa4c68f1852295fd553a7dce2bb760e6d72 Mon Sep 17 00:00:00 2001 From: Johannes Nussbaum Date: Mon, 7 Aug 2023 16:08:59 +0200 Subject: [PATCH 4/4] improve naming, typing, and docstring --- src/dsp_tools/fast_xmlupload/process_files.py | 4 +-- src/dsp_tools/fast_xmlupload/upload_files.py | 4 +-- src/dsp_tools/models/sipi.py | 4 +-- src/dsp_tools/utils/shared.py | 28 ++++++++++++------- src/dsp_tools/utils/stack_handling.py | 14 +++++----- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/dsp_tools/fast_xmlupload/process_files.py b/src/dsp_tools/fast_xmlupload/process_files.py index 3fc2f5ad0e..5dba49eaa3 100644 --- a/src/dsp_tools/fast_xmlupload/process_files.py +++ b/src/dsp_tools/fast_xmlupload/process_files.py @@ -20,7 +20,7 @@ from dsp_tools.models.exceptions import UserError from dsp_tools.utils.logging import get_logger -from dsp_tools.utils.shared import try_api_call +from dsp_tools.utils.shared import http_call_with_retry logger = get_logger(__name__, filesize_mb=100, backupcount=36) sipi_container: Optional[Container] = None @@ -35,7 +35,7 @@ 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 = try_api_call( + 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", ) diff --git a/src/dsp_tools/fast_xmlupload/upload_files.py b/src/dsp_tools/fast_xmlupload/upload_files.py index 3fc1f1dbb0..7057792f6f 100644 --- a/src/dsp_tools/fast_xmlupload/upload_files.py +++ b/src/dsp_tools/fast_xmlupload/upload_files.py @@ -11,7 +11,7 @@ from dsp_tools.models.connection import Connection from dsp_tools.models.exceptions import BaseError from dsp_tools.utils.logging import get_logger -from dsp_tools.utils.shared import try_api_call, login +from dsp_tools.utils.shared import http_call_with_retry, login logger = get_logger(__name__) @@ -110,7 +110,7 @@ def _upload_without_processing( try: with open(file, "rb") as bitstream: try: - response_upload = try_api_call( + response_upload = http_call_with_retry( action=requests.post, initial_timeout=8 * 60, url=f"{regex.sub(r'/$', '', sipi_url)}/upload_without_processing", diff --git a/src/dsp_tools/models/sipi.py b/src/dsp_tools/models/sipi.py index a34c36945c..40fad39dae 100644 --- a/src/dsp_tools/models/sipi.py +++ b/src/dsp_tools/models/sipi.py @@ -7,7 +7,7 @@ from dsp_tools.models.connection import check_for_api_error -from dsp_tools.utils.shared import try_api_call +from dsp_tools.utils.shared import http_call_with_retry class Sipi: @@ -31,7 +31,7 @@ def upload_bitstream(self, filepath: str) -> dict[Any, Any]: files = { "file": (os.path.basename(filepath), bitstream_file), } - response = try_api_call( + response = http_call_with_retry( action=requests.post, initial_timeout=5 * 60, url=self.sipi_server + "/upload", diff --git a/src/dsp_tools/utils/shared.py b/src/dsp_tools/utils/shared.py index 820d86ee46..5a8878bee8 100644 --- a/src/dsp_tools/utils/shared.py +++ b/src/dsp_tools/utils/shared.py @@ -7,7 +7,7 @@ import unicodedata from datetime import datetime from pathlib import Path -from typing import Any, Callable, Optional, Union +from typing import Any, Callable, Optional, Union, cast import pandas as pd import regex @@ -54,14 +54,16 @@ def login( return con -def try_api_call( +def http_call_with_retry( action: Callable[..., Any], *args: Any, initial_timeout: int = 10, **kwargs: Any, -) -> Any: +) -> requests.Response: """ - Function that tries 7 times to execute an API call. + 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. @@ -69,23 +71,29 @@ def try_api_call( action: one of requests.get(), requests.post(), requests.put(), requests.delete() initial_timeout: Timeout to start with. Defaults to 10 seconds. + Raises: + errors from the requests library that are not timeouts + Returns: - _description_ + 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 requests.") + 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='{action}', args='{args}', kwargs='{kwargs}'" timeout = initial_timeout for i in range(7): try: if args and not kwargs: - return action(*args, timeout=timeout) + result = action(*args, timeout=timeout) elif kwargs and not args: - return action(**kwargs, timeout=timeout) + result = action(**kwargs, timeout=timeout) elif args and kwargs: - return action(*args, **kwargs, timeout=timeout) + result = action(*args, **kwargs, timeout=timeout) else: - return action(timeout=timeout) + 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..." diff --git a/src/dsp_tools/utils/stack_handling.py b/src/dsp_tools/utils/stack_handling.py index 3e080e373b..234fa2669f 100644 --- a/src/dsp_tools/utils/stack_handling.py +++ b/src/dsp_tools/utils/stack_handling.py @@ -13,7 +13,7 @@ from dsp_tools.models.exceptions import UserError from dsp_tools.utils.logging import get_logger -from dsp_tools.utils.shared import try_api_call +from dsp_tools.utils.shared import http_call_with_retry logger = get_logger(__name__) @@ -123,7 +123,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 = try_api_call( + docker_config_lua_response = http_call_with_retry( action=requests.get, url=f"{self.__url_prefix}sipi/config/sipi.docker-config.lua", ) @@ -165,7 +165,7 @@ def _wait_for_fuseki(self) -> None: """ for _ in range(6 * 60): try: - response = try_api_call( + response = http_call_with_retry( action=requests.get, url="http://0.0.0.0:3030/$/server", auth=("admin", "test"), @@ -184,13 +184,13 @@ def _create_knora_test_repo(self) -> None: Raises: UserError: in case of failure """ - repo_template_response = try_api_call( + repo_template_response = http_call_with_retry( action=requests.get, url=f"{self.__url_prefix}webapi/scripts/fuseki-repository-config.ttl.template", ) repo_template = repo_template_response.text repo_template = repo_template.replace("@REPOSITORY@", "knora-test") - response = try_api_call( + response = http_call_with_retry( action=requests.post, initial_timeout=10, url="http://0.0.0.0:3030/$/datasets", @@ -227,13 +227,13 @@ 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 = try_api_call(action=requests.get, url=self.__url_prefix + ttl_file) + ttl_response = http_call_with_retry(action=requests.get, url=self.__url_prefix + ttl_file) 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 = try_api_call( + response = http_call_with_retry( action=requests.post, initial_timeout=10, url=graph_prefix + graph,