Skip to content

fix: Skip async tests under gevent

5ea3aac
Select commit
Loading
Failed to load commit list.
Sign in for the full log view
Open

feat: Add experimental async transport (port of PR #4572) #5646

fix: Skip async tests under gevent
5ea3aac
Select commit
Loading
Failed to load commit list.
GitHub Actions / warden: code-review completed Mar 12, 2026 in 13m 14s

5 issues

code-review: Found 5 issues (1 high, 3 medium, 1 low)

High

Client reports never flushed in AsyncHttpTransport.flush() - coroutine not awaited - `sentry_sdk/transport.py:878`

At line 878, lambda: self._flush_client_reports(force=True) submits a sync lambda that returns a coroutine without awaiting it. The AsyncWorker._process_callback method awaits the callback itself (await callback()), but since the lambda is synchronous, this completes immediately and returns the coroutine object from _flush_client_reports, which is then discarded without being awaited. This means client reports are silently never sent during flush operations.

Medium

RuntimeError when calling run_until_complete on a closed loop - `sentry_sdk/integrations/asyncio.py:80-88`

The _patched_close() function calls loop.run_until_complete(_flush()) on the loop that is being closed. However, if the loop is already stopped (but not yet closed), or has pending callbacks that haven't been drained, this can cause a RuntimeError with message 'This event loop is already running' in some scenarios (e.g., nested event loops or when called from within an async context). While the try/except block catches exceptions, the root cause is that run_until_complete is being called on a loop that may be in an inconsistent state.

Test will fail: isinstance() check fails on Mock with spec - `tests/integrations/asyncio/test_asyncio.py:665-667`

The test uses Mock(spec=AsyncHttpTransport) but Python's isinstance() does not consider mock objects with specs as instances of the spec class. In _flush(), the check if not isinstance(client.transport, AsyncHttpTransport) evaluates to True (since the mock is not a real AsyncHttpTransport instance), causing an early return before close_async() is called. The assertion mock_client.close_async.assert_called_once() will fail.

httpcore[asyncio] dependency may break py3.6/py3.7 test environments - `tox.ini:340`

The common: httpcore[asyncio] dependency (line 340) is added without a Python version constraint, but httpcore 1.x requires Python 3.8+. The common test environment runs on py3.6 and py3.7 (line 21). This will likely cause pip to fail when creating those test environments since it cannot satisfy the httpcore dependency. Consider using a version-specific constraint like {py3.8,py3.9,py3.10,py3.11,py3.12,py3.13,py3.14,py3.14t}-common: httpcore[asyncio].

Low

Test lacks global scope client cleanup - `tests/test_transport.py:1030`

The test test_async_transport_background_thread_capture sets sentry_sdk.get_global_scope().set_client(client) but does not clean up the global scope after the test completes. This could cause test pollution if subsequent tests depend on global scope state. The similar test test_transport_works_async in the same PR properly uses request.addfinalizer for cleanup.

Also found at:

  • tests/test_transport.py:1061

Duration: 13m 7s · Tokens: 4.9M in / 55.9k out · Cost: $7.62 (+extraction: $0.00, +merge: $0.00, +fix_gate: $0.01)

Annotations

Check failure on line 878 in sentry_sdk/transport.py

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

Client reports never flushed in AsyncHttpTransport.flush() - coroutine not awaited

At line 878, `lambda: self._flush_client_reports(force=True)` submits a sync lambda that returns a coroutine without awaiting it. The `AsyncWorker._process_callback` method awaits the callback itself (`await callback()`), but since the lambda is synchronous, this completes immediately and returns the coroutine object from `_flush_client_reports`, which is then discarded without being awaited. This means client reports are silently never sent during flush operations.

Check warning on line 88 in sentry_sdk/integrations/asyncio.py

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

RuntimeError when calling run_until_complete on a closed loop

The `_patched_close()` function calls `loop.run_until_complete(_flush())` on the loop that is being closed. However, if the loop is already stopped (but not yet closed), or has pending callbacks that haven't been drained, this can cause a `RuntimeError` with message 'This event loop is already running' in some scenarios (e.g., nested event loops or when called from within an async context). While the try/except block catches exceptions, the root cause is that `run_until_complete` is being called on a loop that may be in an inconsistent state.

Check warning on line 667 in tests/integrations/asyncio/test_asyncio.py

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

Test will fail: isinstance() check fails on Mock with spec

The test uses `Mock(spec=AsyncHttpTransport)` but Python's `isinstance()` does not consider mock objects with specs as instances of the spec class. In `_flush()`, the check `if not isinstance(client.transport, AsyncHttpTransport)` evaluates to `True` (since the mock is not a real AsyncHttpTransport instance), causing an early return before `close_async()` is called. The assertion `mock_client.close_async.assert_called_once()` will fail.

Check warning on line 340 in tox.ini

See this annotation in the file changed.

@github-actions github-actions / warden: code-review

httpcore[asyncio] dependency may break py3.6/py3.7 test environments

The `common: httpcore[asyncio]` dependency (line 340) is added without a Python version constraint, but httpcore 1.x requires Python 3.8+. The common test environment runs on py3.6 and py3.7 (line 21). This will likely cause pip to fail when creating those test environments since it cannot satisfy the httpcore dependency. Consider using a version-specific constraint like `{py3.8,py3.9,py3.10,py3.11,py3.12,py3.13,py3.14,py3.14t}-common: httpcore[asyncio]`.