Skip to content

Commit

Permalink
edit
Browse files Browse the repository at this point in the history
  • Loading branch information
jnussbaum committed Oct 18, 2023
1 parent d2c9d61 commit 7aeb41d
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 30 deletions.
8 changes: 6 additions & 2 deletions dsp_permissions_scripts/ap/ap_get.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from dsp_permissions_scripts.utils.authentication import get_protocol
from dsp_permissions_scripts.utils.get_logger import get_logger
from dsp_permissions_scripts.utils.project import get_project_iri_by_shortcode
from dsp_permissions_scripts.utils.try_request import http_call_with_retry

logger = get_logger(__name__)

Expand Down Expand Up @@ -46,9 +47,12 @@ def _get_all_aps_of_project(
project_iri = quote_plus(project_iri, safe="")
protocol = get_protocol(host)
url = f"{protocol}://{host}/admin/permissions/ap/{project_iri}"
response = requests.get(url, headers=headers, timeout=10)
response = http_call_with_retry(
action=lambda: requests.get(url, headers=headers, timeout=10),
err_msg=f"Could not get APs of project {project_iri}",
)
if response.status_code != 200:
raise ApiError("Could not get APs of project", response.text, response.status_code)
raise ApiError(f"Could not get APs of project {project_iri}", response.text, response.status_code)
aps: list[dict[str, Any]] = response.json()["administrative_permissions"]
ap_objects = [create_ap_from_admin_route_object(ap) for ap in aps]
return ap_objects
Expand Down
11 changes: 9 additions & 2 deletions dsp_permissions_scripts/ap/ap_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from dsp_permissions_scripts.models.api_error import ApiError
from dsp_permissions_scripts.utils.authentication import get_protocol
from dsp_permissions_scripts.utils.get_logger import get_logger
from dsp_permissions_scripts.utils.try_request import http_call_with_retry

logger = get_logger(__name__)

Expand All @@ -25,7 +26,10 @@ def _delete_ap_on_server(
ap_iri = quote_plus(ap.iri, safe="")
protocol = get_protocol(host)
url = f"{protocol}://{host}/admin/permissions/{ap_iri}"
response = requests.delete(url, headers=headers, timeout=10)
response = http_call_with_retry(
action=lambda: requests.delete(url, headers=headers, timeout=10),
err_msg=f"Could not delete Administrative Permission {ap.iri}",
)
if response.status_code != 200:
raise ApiError(f"Could not delete Administrative Permission {ap.iri}", response.text, response.status_code)

Expand All @@ -40,7 +44,10 @@ def _update_ap_on_server(
protocol = get_protocol(host)
url = f"{protocol}://{host}/admin/permissions/{iri}/hasPermissions"
payload = {"hasPermissions": create_admin_route_object_from_ap(ap)["hasPermissions"]}
response = requests.put(url, headers=headers, json=payload, timeout=10)
response = http_call_with_retry(
action=lambda: requests.put(url, headers=headers, json=payload, timeout=10),
err_msg=f"Could not update Administrative Permission {ap.iri}",
)
if response.status_code != 200:
raise ApiError(
message=f"Could not update Administrative Permission {ap.iri}",
Expand Down
6 changes: 5 additions & 1 deletion dsp_permissions_scripts/doap/doap_get.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from dsp_permissions_scripts.utils.scope_serialization import (
create_scope_from_admin_route_object,
)
from dsp_permissions_scripts.utils.try_request import http_call_with_retry

logger = get_logger(__name__)

Expand Down Expand Up @@ -44,7 +45,10 @@ def _get_all_doaps_of_project(
project_iri = quote_plus(project_iri, safe="")
protocol = get_protocol(host)
url = f"{protocol}://{host}/admin/permissions/doap/{project_iri}"
response = requests.get(url, headers=headers, timeout=10)
response = http_call_with_retry(
action=lambda: requests.get(url, headers=headers, timeout=10),
err_msg=f"Error while getting DOAPs of project {project_iri}",
)
if response.status_code != 200:
raise ApiError(f"Error while getting DOAPs of project {project_iri}", response.text, response.status_code)
doaps: list[dict[str, Any]] = response.json()["default_object_access_permissions"]
Expand Down
6 changes: 5 additions & 1 deletion dsp_permissions_scripts/doap/doap_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from dsp_permissions_scripts.utils.scope_serialization import (
create_admin_route_object_from_scope,
)
from dsp_permissions_scripts.utils.try_request import http_call_with_retry

logger = get_logger(__name__)

Expand All @@ -27,7 +28,10 @@ def _update_doap_scope_on_server(
protocol = get_protocol(host)
url = f"{protocol}://{host}/admin/permissions/{iri}/hasPermissions"
payload = {"hasPermissions": create_admin_route_object_from_scope(scope)}
response = requests.put(url, headers=headers, json=payload, timeout=10)
response = http_call_with_retry(
action=lambda: requests.put(url, headers=headers, json=payload, timeout=10),
err_msg=f"Could not update scope of DOAP {doap_iri}",
)
if response.status_code != 200:
raise ApiError( f"Could not update scope of DOAP {doap_iri}", response.text, response.status_code, payload)
new_doap = create_doap_from_admin_route_response(response.json()["default_object_access_permission"])
Expand Down
16 changes: 13 additions & 3 deletions dsp_permissions_scripts/oap/oap_get_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from dsp_permissions_scripts.utils.authentication import get_protocol
from dsp_permissions_scripts.utils.get_logger import get_logger
from dsp_permissions_scripts.utils.scope_serialization import create_string_from_scope
from dsp_permissions_scripts.utils.try_request import http_call_with_retry

logger = get_logger(__name__)

Expand Down Expand Up @@ -45,7 +46,10 @@ def _get_resource(
protocol = get_protocol(host)
url = f"{protocol}://{host}/v2/resources/{iri}"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers, timeout=10)
response = http_call_with_retry(
action=lambda: requests.get(url, headers=headers, timeout=10),
err_msg=f"Error while getting resource {resource_iri}",
)
if response.status_code != 200:
raise ApiError( f"Error while getting resource {resource_iri}", response.text, response.status_code)
data: dict[str, Any] = response.json()
Expand Down Expand Up @@ -75,7 +79,10 @@ def _update_permissions_for_value(
protocol = get_protocol(host)
url = f"{protocol}://{host}/v2/values"
headers = {"Authorization": f"Bearer {token}"}
response = requests.put(url, headers=headers, json=payload, timeout=10)
response = http_call_with_retry(
action=lambda: requests.put(url, headers=headers, json=payload, timeout=10),
err_msg=f"Error while updating permissions of resource {resource_iri}, value {value.value_iri}",
)
if response.status_code == 400 and response.text:
already = "dsp.errors.BadRequestException: The submitted permissions are the same as the current ones"
if already in response.text:
Expand Down Expand Up @@ -113,7 +120,10 @@ def _update_permissions_for_resource(
protocol = get_protocol(host)
url = f"{protocol}://{host}/v2/resources"
headers = {"Authorization": f"Bearer {token}"}
response = requests.put(url, headers=headers, json=payload, timeout=10)
response = http_call_with_retry(
action=lambda: requests.put(url, headers=headers, json=payload, timeout=10),
err_msg=f"ERROR while updating permissions of resource {resource_iri}",
)
if response.status_code != 200:
raise ApiError(
message=f"ERROR while updating permissions of resource {resource_iri}",
Expand Down
21 changes: 17 additions & 4 deletions dsp_permissions_scripts/utils/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from dsp_permissions_scripts.utils.get_logger import get_logger
from dsp_permissions_scripts.utils.helpers import dereference_prefix
from dsp_permissions_scripts.utils.scope_serialization import create_scope_from_string
from dsp_permissions_scripts.utils.try_request import http_call_with_retry

logger = get_logger(__name__)

Expand Down Expand Up @@ -45,7 +46,10 @@ def _get_onto_iris_of_project(
protocol = get_protocol(host)
url = f"{protocol}://{host}/v2/ontologies/metadata"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers, timeout=10)
response = http_call_with_retry(
action=lambda: requests.get(url, headers=headers, timeout=10),
err_msg="Could not get onto IRIs",
)
if response.status_code != 200:
raise ApiError("Could not get onto IRIs", response.text, response.status_code)
all_ontologies = response.json().get("@graph")
Expand All @@ -61,7 +65,10 @@ def _get_class_iris_of_onto(
protocol = get_protocol(host)
url = f"{protocol}://{host}/v2/ontologies/allentities/{quote_plus(onto_iri)}"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers, timeout=10)
response = http_call_with_retry(
action=lambda: requests.get(url, headers=headers, timeout=10),
err_msg="Could not get class IRIs",
)
if response.status_code != 200:
raise ApiError("Could not get class IRIs", response.text, response.status_code)
all_entities = response.json()["@graph"]
Expand Down Expand Up @@ -121,7 +128,10 @@ def _get_next_page(
This means that the page must be incremented until the response contains 0 or 1 resource.
"""
url = f"{protocol}://{host}/v2/resources?resourceClass={quote_plus(resclass_iri)}&page={page}"
response = requests.get(url, headers=headers, timeout=20)
response = http_call_with_retry(
action=lambda: requests.get(url, headers=headers, timeout=20),
err_msg="Could not get next page",
)
if response.status_code != 200:
raise ApiError("Could not get next page", response.text, response.status_code)
result = response.json()
Expand All @@ -144,7 +154,10 @@ def _get_next_page(
def get_project_iri_by_shortcode(shortcode: str, host: str) -> str:
protocol = get_protocol(host)
url = f"{protocol}://{host}/admin/projects/shortcode/{shortcode}"
response = requests.get(url, timeout=10)
response = http_call_with_retry(
action=lambda: requests.get(url, timeout=10),
err_msg="Cannot retrieve project IRI",
)
if response.status_code != 200:
raise ApiError("Cannot retrieve project IRI", response.text, response.status_code)
iri: str = response.json()["project"]["id"]
Expand Down
32 changes: 15 additions & 17 deletions dsp_permissions_scripts/utils/try_request.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@


import time
from typing import Any, Callable
from typing import Callable

import requests
from requests import ReadTimeout
from requests import ReadTimeout, RequestException
from urllib3.exceptions import ReadTimeoutError

from dsp_permissions_scripts.utils.get_logger import get_logger, get_timestamp

logger = get_logger(__name__)


def http_call_with_retry(
action: Callable[..., Any],
) -> requests.Response:
def http_call_with_retry(action: Callable[..., requests.Response], err_msg: str) -> requests.Response:
"""
Function that tries 7 times to execute an HTTP request.
502 and 404 are catched, and the request is retried after a waiting time.
Expand All @@ -22,27 +19,28 @@ def http_call_with_retry(
Args:
action: one of requests.get(), requests.post(), requests.put(), requests.delete()
err_msg: this message is printed and logged when there is a problem with the call
Raises:
ValueError: if the action is not one of one of requests.get/post/put/delete
Other Errors: errors from the requests library
errors from the requests library
Returns:
response of the HTTP request
"""
if action not in (requests.get, requests.post, requests.put, requests.delete):
raise ValueError(
"This function can only be used with the methods get, post, put, and delete of the Python requests library."
)
for i in range(7):
try:
response: requests.Response = action()
if response.status_code in [502, 404]:
print(f"{get_timestamp()}: Server Error: Retry request in {2 ** i} seconds...")
logger.error(f"Server Error: Retry request in {2 ** i} seconds... ({response.status_code}: {response.text})")
if response.status_code == 200:
return response
retry_code = 500 <= response.status_code < 600 or response.status_code == 404
try_again_later = "try again later" in response.text
if retry_code or try_again_later:
msg = f"{err_msg}. Retry request in {2 ** i} seconds... ({response.status_code}: {response.text})"
print(f"{get_timestamp()}: SERVER ERROR: {msg}")
logger.error(msg)
continue
return response
except (TimeoutError, ReadTimeout, ReadTimeoutError):
except (TimeoutError, ReadTimeout, ReadTimeoutError, RequestException, ConnectionError):
print(f"{get_timestamp()}: Server Error: Retry request in {2 ** i} seconds...")
logger.error(f"Server Error: Retry request in {2 ** i} seconds...", exc_info=True)
time.sleep(2**i)
Expand Down

0 comments on commit 7aeb41d

Please sign in to comment.