Skip to content

Commit 5f02b64

Browse files
authored
Merge pull request #288 from opsmill/lgu-fix-url-not-found
Raise URLNotFoundError instead of infinite retry
2 parents 0988b2b + fd67def commit 5f02b64

File tree

6 files changed

+35
-5
lines changed

6 files changed

+35
-5
lines changed

docs/docs/python-sdk/reference/config.mdx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,15 @@ The following settings can be defined in the `Config` class
150150
**Default value**: False<br />
151151
**Environment variable**: `INFRAHUB_RETRY_ON_FAILURE`<br />
152152
<!-- vale off -->
153+
## max_retry_duration
154+
155+
**Property**: max_retry_duration<br />
156+
<!-- vale on -->
157+
**Description**: Maximum duration until we stop attempting to retry if enabled.<br />
158+
**Type**: `integer`<br />
159+
**Default value**: 300<br />
160+
**Environment variable**: `INFRAHUB_MAX_RETRY_DURATION`<br />
161+
<!-- vale off -->
153162
## schema_converge_timeout
154163

155164
**Property**: schema_converge_timeout<br />

infrahub_sdk/client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import asyncio
44
import copy
55
import logging
6+
import time
67
from collections.abc import Coroutine, MutableMapping
78
from functools import wraps
89
from time import sleep
@@ -38,6 +39,7 @@
3839
NodeNotFoundError,
3940
ServerNotReachableError,
4041
ServerNotResponsiveError,
42+
URLNotFoundError,
4143
)
4244
from .graphql import Mutation, Query
4345
from .node import (
@@ -878,7 +880,8 @@ async def execute_graphql(
878880

879881
retry = True
880882
resp = None
881-
while retry:
883+
start_time = time.time()
884+
while retry and time.time() - start_time < self.config.max_retry_duration:
882885
retry = self.retry_on_failure
883886
try:
884887
resp = await self._post(url=url, payload=payload, headers=headers, timeout=timeout)
@@ -902,6 +905,8 @@ async def execute_graphql(
902905
errors = response.get("errors", [])
903906
messages = [error.get("message") for error in errors]
904907
raise AuthenticationError(" | ".join(messages)) from exc
908+
if exc.response.status_code == 404:
909+
raise URLNotFoundError(url=url)
905910

906911
if not resp:
907912
raise Error("Unexpected situation, resp hasn't been initialized.")
@@ -1613,7 +1618,8 @@ def execute_graphql(
16131618

16141619
retry = True
16151620
resp = None
1616-
while retry:
1621+
start_time = time.time()
1622+
while retry and time.time() - start_time < self.config.max_retry_duration:
16171623
retry = self.retry_on_failure
16181624
try:
16191625
resp = self._post(url=url, payload=payload, headers=headers, timeout=timeout)
@@ -1637,6 +1643,8 @@ def execute_graphql(
16371643
errors = response.get("errors", [])
16381644
messages = [error.get("message") for error in errors]
16391645
raise AuthenticationError(" | ".join(messages)) from exc
1646+
if exc.response.status_code == 404:
1647+
raise URLNotFoundError(url=url)
16401648

16411649
if not resp:
16421650
raise Error("Unexpected situation, resp hasn't been initialized.")

infrahub_sdk/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class ConfigBase(BaseSettings):
5656
pagination_size: int = Field(default=50, description="Page size for queries to the server")
5757
retry_delay: int = Field(default=5, description="Number of seconds to wait until attempting a retry.")
5858
retry_on_failure: bool = Field(default=False, description="Retry operation in case of failure")
59+
max_retry_duration: int = Field(
60+
default=300, description="Maximum duration until we stop attempting to retry if enabled."
61+
)
5962
schema_converge_timeout: int = Field(
6063
default=60, description="Number of seconds to wait for schema to have converged"
6164
)

infrahub_sdk/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ def __init__(self, message: str | None = None):
121121
super().__init__(self.message)
122122

123123

124+
class URLNotFoundError(Error):
125+
def __init__(self, url: str):
126+
self.message = f"`{url}` not found."
127+
super().__init__(self.message)
128+
129+
124130
class FeatureNotSupportedError(Error):
125131
"""Raised when trying to use a method on a node that doesn't support it."""
126132

tasks.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,6 @@ def generate_infrahubctl(context: Context) -> None:
181181

182182

183183
@task(name="generate-sdk")
184-
def generate_python_sdk(context: Context) -> None:
184+
def generate_python_sdk(context: Context) -> None: # noqa: ARG001
185185
"""Generate documentation for the Python SDK."""
186-
_generate_infrahub_sdk_configuration_documentation(context=context)
186+
_generate_infrahub_sdk_configuration_documentation()

tests/integration/test_infrahub_client.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pytest
66

77
from infrahub_sdk.branch import BranchData
8-
from infrahub_sdk.exceptions import BranchNotFoundError
8+
from infrahub_sdk.exceptions import BranchNotFoundError, URLNotFoundError
99
from infrahub_sdk.node import InfrahubNode
1010
from infrahub_sdk.schema import ProfileSchemaAPI
1111
from infrahub_sdk.testing.docker import TestInfrahubDockerClient
@@ -146,6 +146,10 @@ async def test_count_with_filter(self, client: InfrahubClient, base_dataset):
146146
count = await client.count(kind=TESTING_PERSON, name__values=["Liam Walker", "Ethan Carter"])
147147
assert count == 2
148148

149+
async def test_query_unexisting_branch(self, client: InfrahubClient):
150+
with pytest.raises(URLNotFoundError, match=r"/graphql/unexisting` not found."):
151+
await client.execute_graphql(query="unused", branch_name="unexisting")
152+
149153
async def test_create_generic_rel_with_hfid(
150154
self, client: InfrahubClient, base_dataset, cat_luna, person_sophia, schema_animal, schema_cat
151155
):

0 commit comments

Comments
 (0)