Skip to content

Commit 1807995

Browse files
Handle non-thread-safe loop runtime errors as non-retryable
Co-authored-by: Shri Sukhani <shrisukhani@users.noreply.github.com>
1 parent dad7cd8 commit 1807995

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

hyperbrowser/client/polling.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ def _is_async_loop_contract_runtime_error(exc: Exception) -> bool:
134134
normalized_message = str(exc).lower()
135135
if "event loop is closed" in normalized_message:
136136
return True
137+
if "event loop other than the current one" in normalized_message:
138+
return True
137139
if "different event loop" in normalized_message:
138140
return True
139141
return "different loop" in normalized_message and any(

tests/test_polling.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,26 @@ def operation() -> str:
12201220
assert attempts["count"] == 1
12211221

12221222

1223+
def test_retry_operation_does_not_retry_runtime_errors_for_non_thread_safe_loop_operation():
1224+
attempts = {"count": 0}
1225+
1226+
def operation() -> str:
1227+
attempts["count"] += 1
1228+
raise RuntimeError(
1229+
"Non-thread-safe operation invoked on an event loop other than the current one"
1230+
)
1231+
1232+
with pytest.raises(RuntimeError, match="event loop other than the current one"):
1233+
retry_operation(
1234+
operation_name="sync retry non-thread-safe loop runtime error",
1235+
operation=operation,
1236+
max_attempts=5,
1237+
retry_delay_seconds=0.0001,
1238+
)
1239+
1240+
assert attempts["count"] == 1
1241+
1242+
12231243
def test_poll_until_terminal_status_async_does_not_retry_runtime_errors_for_closed_loop():
12241244
async def run() -> None:
12251245
attempts = {"count": 0}
@@ -1243,6 +1263,31 @@ async def get_status() -> str:
12431263
asyncio.run(run())
12441264

12451265

1266+
def test_poll_until_terminal_status_async_does_not_retry_runtime_errors_for_non_thread_safe_loop_operation():
1267+
async def run() -> None:
1268+
attempts = {"count": 0}
1269+
1270+
async def get_status() -> str:
1271+
attempts["count"] += 1
1272+
raise RuntimeError(
1273+
"Non-thread-safe operation invoked on an event loop other than the current one"
1274+
)
1275+
1276+
with pytest.raises(RuntimeError, match="event loop other than the current one"):
1277+
await poll_until_terminal_status_async(
1278+
operation_name="async poll non-thread-safe loop runtime error",
1279+
get_status=get_status,
1280+
is_terminal_status=lambda value: value == "completed",
1281+
poll_interval_seconds=0.0001,
1282+
max_wait_seconds=1.0,
1283+
max_status_failures=5,
1284+
)
1285+
1286+
assert attempts["count"] == 1
1287+
1288+
asyncio.run(run())
1289+
1290+
12461291
def test_poll_until_terminal_status_async_does_not_retry_runtime_errors_for_event_loop_binding():
12471292
async def run() -> None:
12481293
attempts = {"count": 0}

0 commit comments

Comments
 (0)