Skip to content

Commit 3b56695

Browse files
Avoid wait-helper fetch name overlength validation failures
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent 72599c8 commit 3b56695

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

hyperbrowser/client/polling.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
T = TypeVar("T")
1919
_MAX_OPERATION_NAME_LENGTH = 200
20+
_FETCH_OPERATION_NAME_PREFIX = "Fetching "
2021
_CLIENT_ERROR_STATUS_MIN = 400
2122
_CLIENT_ERROR_STATUS_MAX = 500
2223
_RETRYABLE_CLIENT_ERROR_STATUS_CODES = {408, 429}
@@ -65,6 +66,13 @@ def _validate_operation_name(operation_name: str) -> None:
6566
raise HyperbrowserError("operation_name must not contain control characters")
6667

6768

69+
def _build_fetch_operation_name(operation_name: str) -> str:
70+
prefixed_operation_name = f"{_FETCH_OPERATION_NAME_PREFIX}{operation_name}"
71+
if len(prefixed_operation_name) <= _MAX_OPERATION_NAME_LENGTH:
72+
return prefixed_operation_name
73+
return operation_name
74+
75+
6876
def _ensure_boolean_terminal_result(result: object, *, operation_name: str) -> bool:
6977
_ensure_non_awaitable(
7078
result, callback_name="is_terminal_status", operation_name=operation_name
@@ -792,8 +800,9 @@ def wait_for_job_result(
792800
max_wait_seconds=max_wait_seconds,
793801
max_status_failures=max_status_failures,
794802
)
803+
fetch_operation_name = _build_fetch_operation_name(operation_name)
795804
return retry_operation(
796-
operation_name=f"Fetching {operation_name}",
805+
operation_name=fetch_operation_name,
797806
operation=fetch_result,
798807
max_attempts=fetch_max_attempts,
799808
retry_delay_seconds=fetch_retry_delay_seconds,
@@ -828,8 +837,9 @@ async def wait_for_job_result_async(
828837
max_wait_seconds=max_wait_seconds,
829838
max_status_failures=max_status_failures,
830839
)
840+
fetch_operation_name = _build_fetch_operation_name(operation_name)
831841
return await retry_operation_async(
832-
operation_name=f"Fetching {operation_name}",
842+
operation_name=fetch_operation_name,
833843
operation=fetch_result,
834844
max_attempts=fetch_max_attempts,
835845
retry_delay_seconds=fetch_retry_delay_seconds,

tests/test_polling.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4031,6 +4031,31 @@ def test_wait_for_job_result_accepts_fraction_timing_values():
40314031
assert result == {"ok": True}
40324032

40334033

4034+
def test_wait_for_job_result_allows_max_length_operation_name():
4035+
fetch_attempts = {"count": 0}
4036+
4037+
def fetch_result() -> dict:
4038+
fetch_attempts["count"] += 1
4039+
if fetch_attempts["count"] < 2:
4040+
raise ValueError("temporary fetch failure")
4041+
return {"ok": True}
4042+
4043+
result = wait_for_job_result(
4044+
operation_name="x" * 200,
4045+
get_status=lambda: "completed",
4046+
is_terminal_status=lambda value: value == "completed",
4047+
fetch_result=fetch_result,
4048+
poll_interval_seconds=0.0001,
4049+
max_wait_seconds=1.0,
4050+
max_status_failures=2,
4051+
fetch_max_attempts=2,
4052+
fetch_retry_delay_seconds=0.0001,
4053+
)
4054+
4055+
assert result == {"ok": True}
4056+
assert fetch_attempts["count"] == 2
4057+
4058+
40344059
def test_wait_for_job_result_status_polling_failures_short_circuit_fetch():
40354060
status_attempts = {"count": 0}
40364061
fetch_attempts = {"count": 0}
@@ -5017,6 +5042,34 @@ async def run() -> None:
50175042
asyncio.run(run())
50185043

50195044

5045+
def test_wait_for_job_result_async_allows_max_length_operation_name():
5046+
async def run() -> None:
5047+
fetch_attempts = {"count": 0}
5048+
5049+
async def fetch_result() -> dict:
5050+
fetch_attempts["count"] += 1
5051+
if fetch_attempts["count"] < 2:
5052+
raise ValueError("temporary fetch failure")
5053+
return {"ok": True}
5054+
5055+
result = await wait_for_job_result_async(
5056+
operation_name="x" * 200,
5057+
get_status=lambda: asyncio.sleep(0, result="completed"),
5058+
is_terminal_status=lambda value: value == "completed",
5059+
fetch_result=fetch_result,
5060+
poll_interval_seconds=0.0001,
5061+
max_wait_seconds=1.0,
5062+
max_status_failures=2,
5063+
fetch_max_attempts=2,
5064+
fetch_retry_delay_seconds=0.0001,
5065+
)
5066+
5067+
assert result == {"ok": True}
5068+
assert fetch_attempts["count"] == 2
5069+
5070+
asyncio.run(run())
5071+
5072+
50205073
def test_wait_for_job_result_async_status_polling_failures_short_circuit_fetch():
50215074
async def run() -> None:
50225075
status_attempts = {"count": 0}

0 commit comments

Comments
 (0)