fix(ci): use module-level engines to avoid event loop teardown crash

Per-test engine creation/disposal triggers asyncpg event loop errors
during pytest-asyncio teardown. Module-level engines are created once
and reused across all tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-15 06:42:30 -05:00
parent 34bb60bd12
commit 402b25f418

View File

@@ -92,30 +92,27 @@ def setup_database():
# ---------------------------------------------------------------------------
@pytest_asyncio.fixture
async def admin_engine():
# Module-level engines — created once, reused across all tests.
# Avoids per-test engine creation/disposal which triggers asyncpg
# event loop issues during pytest-asyncio teardown.
_admin_engine = create_async_engine(
TEST_DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=5, max_overflow=5
)
_app_engine = create_async_engine(
TEST_APP_USER_DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=5, max_overflow=5
)
@pytest.fixture
def admin_engine():
"""Admin engine (superuser) -- bypasses RLS."""
engine = create_async_engine(
TEST_DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=5, max_overflow=5
)
yield engine
try:
await engine.dispose()
except RuntimeError:
pass # Event loop may be closed during final teardown
return _admin_engine
@pytest_asyncio.fixture
async def app_engine():
@pytest.fixture
def app_engine():
"""App-user engine -- RLS enforced."""
engine = create_async_engine(
TEST_APP_USER_DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=5, max_overflow=5
)
yield engine
try:
await engine.dispose()
except RuntimeError:
pass # Event loop may be closed during final teardown
return _app_engine
# ---------------------------------------------------------------------------