mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
fix: Prevent retry_on_errors from retrying asyncio.CancelledError
The retry_on_errors decorator in mcp_session_manager.py now catches asyncio.CancelledError and re-raises it immediately, ensuring that cancellation requests are not suppressed or retried Close #4009 Co-authored-by: George Weale <gweale@google.com> PiperOrigin-RevId: 852468382
This commit is contained in:
committed by
Copybara-Service
parent
6f2c70fc33
commit
30d3411d60
@@ -391,7 +391,8 @@ class TestMCPSessionManager:
|
||||
assert "Close error 1" in error_output
|
||||
|
||||
|
||||
def test_retry_on_errors_decorator():
|
||||
@pytest.mark.asyncio
|
||||
async def test_retry_on_errors_decorator():
|
||||
"""Test the retry_on_errors decorator."""
|
||||
|
||||
call_count = 0
|
||||
@@ -401,23 +402,77 @@ def test_retry_on_errors_decorator():
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
if call_count == 1:
|
||||
import anyio
|
||||
|
||||
raise anyio.ClosedResourceError("Resource closed")
|
||||
raise ConnectionError("Resource closed")
|
||||
return "success"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_retry():
|
||||
mock_self = Mock()
|
||||
result = await mock_function(mock_self)
|
||||
|
||||
assert result == "success"
|
||||
assert call_count == 2 # First call fails, second succeeds
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_retry_on_errors_decorator_does_not_retry_cancelled_error():
|
||||
"""Test the retry_on_errors decorator does not retry cancellation."""
|
||||
|
||||
call_count = 0
|
||||
|
||||
@retry_on_errors
|
||||
async def mock_function(self):
|
||||
nonlocal call_count
|
||||
call_count = 0
|
||||
call_count += 1
|
||||
raise asyncio.CancelledError()
|
||||
|
||||
mock_self = Mock()
|
||||
result = await mock_function(mock_self)
|
||||
mock_self = Mock()
|
||||
with pytest.raises(asyncio.CancelledError):
|
||||
await mock_function(mock_self)
|
||||
|
||||
assert result == "success"
|
||||
assert call_count == 2 # First call fails, second succeeds
|
||||
assert call_count == 1
|
||||
|
||||
# Run the test
|
||||
import asyncio
|
||||
|
||||
asyncio.run(test_retry())
|
||||
@pytest.mark.asyncio
|
||||
async def test_retry_on_errors_decorator_does_not_retry_when_task_is_cancelling():
|
||||
"""Test the retry_on_errors decorator does not retry when cancelling."""
|
||||
|
||||
call_count = 0
|
||||
|
||||
@retry_on_errors
|
||||
async def mock_function(self):
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
raise ConnectionError("Resource closed")
|
||||
|
||||
class _MockTask:
|
||||
|
||||
def cancelling(self):
|
||||
return 1
|
||||
|
||||
mock_self = Mock()
|
||||
with patch.object(asyncio, "current_task", return_value=_MockTask()):
|
||||
with pytest.raises(ConnectionError):
|
||||
await mock_function(mock_self)
|
||||
|
||||
assert call_count == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_retry_on_errors_decorator_does_not_retry_exception_from_cancel():
|
||||
"""Test the retry_on_errors decorator does not retry exceptions on cancel."""
|
||||
|
||||
call_count = 0
|
||||
|
||||
@retry_on_errors
|
||||
async def mock_function(self):
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
try:
|
||||
raise asyncio.CancelledError()
|
||||
except asyncio.CancelledError:
|
||||
raise ConnectionError("Resource closed")
|
||||
|
||||
mock_self = Mock()
|
||||
with pytest.raises(ConnectionError):
|
||||
await mock_function(mock_self)
|
||||
|
||||
assert call_count == 1
|
||||
|
||||
Reference in New Issue
Block a user