diff --git a/src/scribe/services/db_maintenance.py b/src/scribe/services/db_maintenance.py index 98a5c40..b01277c 100644 --- a/src/scribe/services/db_maintenance.py +++ b/src/scribe/services/db_maintenance.py @@ -66,9 +66,10 @@ async def run_maintenance(tables: tuple[str, ...] | list[str] | None = None) -> results: list[dict] = [] async with engine.connect() as conn: - # execution_options() is synchronous on AsyncConnection; it returns the - # connection with AUTOCOMMIT set (VACUUM can't run in a transaction). - autocommit = conn.execution_options(isolation_level="AUTOCOMMIT") + # On AsyncConnection, execution_options() is a coroutine and MUST be + # awaited (it returns the connection with AUTOCOMMIT set — VACUUM can't + # run inside a transaction block). + autocommit = await conn.execution_options(isolation_level="AUTOCOMMIT") for table in targets: t0 = time.monotonic() try: diff --git a/tests/test_services_db_maintenance.py b/tests/test_services_db_maintenance.py index 0b32397..8b5860e 100644 --- a/tests/test_services_db_maintenance.py +++ b/tests/test_services_db_maintenance.py @@ -16,7 +16,9 @@ def _mock_engine(exec_side_effect=None): conn = MagicMock() autocommit = MagicMock() autocommit.exec_driver_sql = AsyncMock(side_effect=exec_side_effect) - conn.execution_options.return_value = autocommit # sync on AsyncConnection + # On AsyncConnection, execution_options() is a coroutine — mock it as async + # so the test exercises the real (awaited) call shape. + conn.execution_options = AsyncMock(return_value=autocommit) cm = AsyncMock() cm.__aenter__ = AsyncMock(return_value=conn) cm.__aexit__ = AsyncMock(return_value=False) @@ -36,9 +38,9 @@ async def test_vacuums_each_allowlisted_table_once(): assert issued == [f"VACUUM (ANALYZE) {t}" for t in MAINTENANCE_TABLES] assert all(r["ok"] for r in summary["tables"]) assert len(summary["tables"]) == len(MAINTENANCE_TABLES) - # AUTOCOMMIT was requested — VACUUM cannot run inside a transaction. + # AUTOCOMMIT was requested (and awaited) — VACUUM can't run in a transaction. conn = engine.connect.return_value.__aenter__.return_value - conn.execution_options.assert_called_once_with(isolation_level="AUTOCOMMIT") + conn.execution_options.assert_awaited_once_with(isolation_level="AUTOCOMMIT") @pytest.mark.asyncio