Skip to content

Commit

Permalink
feat!: allow users to specify arbitrary retry stopping criteria" -m "…
Browse files Browse the repository at this point in the history
…BREAKING CHANGE: num_retries is no longer available as ServiceConfig
  • Loading branch information
davidkleiven committed Sep 3, 2024
1 parent a38de47 commit dec7293
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 4 deletions.
10 changes: 8 additions & 2 deletions cimsparql/graphdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import tenacity
from SPARQLWrapper import JSON, POST, SPARQLWrapper
from strenum import StrEnum
from tenacity.stop import stop_base

from cimsparql.retry_cb import RetryCallback, RetryCallbackFactory
from cimsparql.sparql_result_json import (
Expand Down Expand Up @@ -68,6 +69,11 @@ def parse_namespaces_rdf4j(response: httpx.Response) -> dict[str, str]:
return dict(line.split(",") for line in response.text.split()[1:])


class NeverStop(stop_base):
def __call__(self, _: tenacity.RetryCallState) -> bool:
return False


@dataclass(frozen=True)
class ServiceConfig:
repo: str = field(default=os.getenv("GRAPHDB_REPO", "LATEST"))
Expand All @@ -80,6 +86,7 @@ class ServiceConfig:
rest_api: RestApi = field(default=RestApi(os.getenv("SPARQL_REST_API", "RDF4J")))
ca_bundle: str | None = field(default=None)
retry_callback_factory: RetryCallbackFactory = field(default=RetryCallback)
retry_stop_criteria: stop_base = field(default=tenacity.stop_after_attempt(1))

# Parameters for rest api
# https://rdf4j.org/documentation/reference/rest-api/
Expand All @@ -88,7 +95,6 @@ class ServiceConfig:
limit: int | None = None
offset: int | None = None
timeout: int | None = None
num_retries: int = 0
max_delay_seconds: int = 60
validate: bool = False

Expand Down Expand Up @@ -241,7 +247,7 @@ def exec_query(self, query: str) -> SparqlResultJson:

sparql_result = None
for attempt in tenacity.Retrying(
stop=tenacity.stop_after_attempt(self.service_cfg.num_retries + 1),
stop=self.service_cfg.retry_stop_criteria,
wait=tenacity.wait_exponential(max=self.service_cfg.max_delay_seconds),
before=retry_cb.before,
after=retry_cb.after,
Expand Down
4 changes: 3 additions & 1 deletion tests/test_retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ def test_retry_sync(
url = fail_first_ok_second_server(httpserver)

config = ServiceConfig(
server=url, rest_api=RestApi.DIRECT_SPARQL_ENDPOINT, num_retries=num_retries
server=url,
rest_api=RestApi.DIRECT_SPARQL_ENDPOINT,
retry_stop_criteria=tenacity.stop_after_attemps(num_retries + 1),
)

client = GraphDBClient(config)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_retry_cb.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def queryAndConvert(self) -> dict[str, Any]: # noqa: N802

def test_after_callback(caplog: pytest.LogCaptureFixture):
wrapper = FailFirstSparqlWrapper("http://some-sparql-endpint")
client = GraphDBClient(service_cfg=ServiceConfig(num_retries=1), sparql_wrapper=wrapper)
client = GraphDBClient(service_cfg=ServiceConfig(), sparql_wrapper=wrapper)
client.exec_query("# Name: Select everything\nselect * where {?s ?p ?o}")

# Expect one message to contain be logged with the query name
Expand Down

0 comments on commit dec7293

Please sign in to comment.