Skip to content

fix: build null and static pools from PoolSettings, and stop recommending the sync queue pool - #61

Merged
AlexeyShalaev merged 1 commit into
masterfrom
fix/53-pool-kwargs
Oct 16, 2026
Merged

AlexeyShalaev merged 1 commit into
masterfrom
fix/53-pool-kwargs

Conversation

@AlexeyShalaev

Copy link
Copy Markdown
Member

Closes #53.

Problem

_apply_pool_settings passed pool_size, max_overflow and pool_timeout to every pool class, so PoolSettings(kind="null") and PoolSettings(kind="static", ...) could not build an engine. PoolSettings always carries all three, so neither kind has ever worked from settings. The docstrings also recommended "queue", a sync pool that SQLAlchemy refuses on an asyncio engine.

Change

  • pool_size, max_overflow and pool_timeout go to the engine only when issubclass(poolclass, QueuePool): the async queue pools, registered subclasses, and the class instrument_pool_class builds. pool_recycle and pool_pre_ping go to every pool. The docstring now describes the code.
  • PoolSettings(kind="static") is documented as what SQLAlchemy builds: one shared connection, for tests. The validator now rejects size > 1 for static, with a message that points at async_adapted_queue plus max_overflow=0, and no longer checks max_overflow, which doesn't apply to it. The "high-throughput static pool" example is gone.
  • AsyncSessionManager(poolclass=None) is the new default. It means pool_settings.kind when pool_settings is given, and "null" otherwise. Without this, the kwargs filter would have turned AsyncSessionManager(url, pool_settings=...) from a crash into a silent NullPool that ignores the sizes.
  • AsyncSessionManager and builder docstrings: "queue" becomes "async_adapted_queue", and "null" is described as one connection per checkout, for tests.

Considered and rejected

  • Dropping "queue"/"singleton_thread" from PoolRegistry, or resolving "queue" to AsyncAdaptedQueuePool. The registry and resolve_pool_class are public and can serve a sync engine (a migrations engine built from the same PoolSettings). Repointing a public name would break that. On the async manager, SQLAlchemy already fails loudly at construction.
  • Making "async_adapted_queue" the manager's default without pool_settings. Test suites that build a manager per test and per event loop rely on NullPool, because a pooled asyncpg connection can't cross loops.

Who notices

  • Anyone with kind="static" and size > 1 now gets a ValidationError at config load. That config never built an engine before (TypeError at create_async_engine), so no working setup changes.
  • PoolSettings(kind="static", max_overflow=20) now validates (overflow doesn't apply). It also never built an engine before.
  • No behaviour change for async_adapted_queue configs or for AsyncSessionManager(url) without pool_settings.

Evidence

New tests, run against the old engine.py/manager.py/settings/postgres.py (swapped in from origin/master): 10 failed, 4 passed. The 4 passing are the queue-pool controls. The failing ones are the NullPool/StaticPool kwargs, every pool kind building an engine from PoolSettings, pool_settings without poolclass, the instrumented static pool, the new validator, and an integration test that runs SELECT 1 through create_async_session_manager for null and static on PostgreSQL 17.

The reporter's script after the fix (static with size=1):

PoolSettings(kind="async_adapted_queue", max_overflow=0)       ok, pool = AsyncAdaptedQueuePool
PoolSettings(kind="null", max_overflow=0)                      ok, pool = NullPool
PoolSettings(kind="static", max_overflow=0)                    ok, pool = StaticPool
AsyncSessionManager(url)                                       ok, pool = NullPool
AsyncSessionManager(url, pool_settings=PoolSettings())         ok, pool = AsyncAdaptedQueuePool
AsyncSessionManager(url, poolclass="queue")                    ArgumentError: Pool class QueuePool cannot be used with asyncio engine

Gate: make check clean; make test 640 passed, coverage 93.77%.

@codecov

codecov Bot commented Oct 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant