1

I am developing a fastapi server using sqlalchemy and asyncpg to work with a postgres database. For each request, a new session is created (via fastapi dependency injection, as in the documentation). I used sqlite+aiosqlite before postgres+asyncpg and everything worked perfectly. After I switched from sqlite to postgres, every fastapi request crashed with the error:

sqlalchemy.dialects.postgresql.asyncpg.InterfaceError - cannot perform operation: another operation is in progress

This is how I create the engine and sessions:

from typing import Generator
import os

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine


user = os.getenv('PG_USER')
password = os.getenv('PG_PASSWORD')
domain = os.getenv('PG_DOMAIN')
db = os.getenv('PG_DATABASE')

# db_async_url = f'sqlite+aiosqlite:///database.sqlite3'
db_async_url = f'postgresql+asyncpg://{user}:{password}@{domain}/{db}'

async_engine = create_async_engine(
    db_async_url, future=True, echo=True
)

create_async_session = sessionmaker(
    async_engine, class_=AsyncSession, expire_on_commit=False
)

async def get_async_session() -> Generator[AsyncSession]:
    async with create_async_session() as session:
        yield session
Mark
  • 55
  • 2
  • 7

1 Answers1

2

The error disappeared after adding poolclass=NullPool to create_async_engine, so here's what engine creation looks like now:

from sqlalchemy.pool import NullPool

...

async_engine = create_async_engine(
    db_async_url, future=True, echo=True, poolclass=NullPool
)

I spent more than a day to solve this problem. I hope my answer will save a lot of time for other developers. Perhaps there are other solutions, and if so, I will be glad to see them here.

Mark
  • 55
  • 2
  • 7
  • 1
    Also, you can try to use `dispose` from your SQLAlchemy engine. Look here https://github.com/tiangolo/fastapi/issues/1800#issuecomment-1260777088 – Andrii Bovsunovskyi Sep 29 '22 at 07:43
  • 1
    Ok but `NullPool` disables connection pooling, so that's not ideal. – Andrew Oct 14 '22 at 01:20
  • Note when using`poolclass == NullPoll` 1. only be used in synchronous calls (db-api) 2. causes opening and closing connection for every query 3. pooling strategy becomes useless – Jagesh Maharjan Nov 01 '22 at 04:36