From dd6ecce78de4751e8676af60774f72530a9e6f56 Mon Sep 17 00:00:00 2001 From: NixReaper Date: Fri, 4 Sep 2026 19:23:18 -0500 Subject: [PATCH] Fix asyncpg cross-event-loop errors in the integration test suite tests/conftest.py's `engine` fixture is session-scoped (one asyncpg engine/schema for the whole run, for speed), but pytest-asyncio's default is a fresh event loop per test function. asyncpg connections are bound to the event loop that created them, so every test after the first failed with "cannot perform operation: another operation is in progress" or "attached to a different loop" the moment it touched the database. Pinning both the fixture and test loop scope to "session" in pyproject.toml keeps everything on one loop, matching the session-scoped engine. Found by actually running the integration suite for the first time, against real PostgreSQL + Redis on a devbox. Co-Authored-By: Claude Sonnet 5 --- pyproject.toml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index f5cf38c..6f9983f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,4 +72,13 @@ exclude = ["migrations", "tests"] [tool.pytest.ini_options] asyncio_mode = "auto" +# The integration test suite shares one session-scoped asyncpg engine +# (tests/conftest.py:engine) across every test, for speed — schema is +# created once instead of per test. asyncpg connections are bound to the +# event loop they were created in, so every fixture/test must run on that +# same loop; pytest-asyncio's default is a fresh loop per test, which +# breaks that assumption ("another operation is in progress" / "attached +# to a different loop"). Pinning both to "session" fixes it. +asyncio_default_fixture_loop_scope = "session" +asyncio_default_test_loop_scope = "session" testpaths = ["tests"]