Coder Social home page Coder Social logo

SQLAlchemy QueuePool limits about fastapi HOT 12 CLOSED

tiangolo avatar tiangolo commented on May 7, 2024
SQLAlchemy QueuePool limits

from fastapi.

Comments (12)

alexiri avatar alexiri commented on May 7, 2024 4

Excellent, thanks! And thanks a lot for the really fast turn-around! You rock!!

from fastapi.

tiangolo avatar tiangolo commented on May 7, 2024 2

@euri10 as always, thanks for the help here!

@alexiri I'm creating a full-stack-fasapi-postgresql project generator and I'm being able to reproduce the issue.


The abstract steps to solve it are:

  • Don't use a scoped_session but a standard Session.
  • Create a session per-request.
  • Close the session after the request is done.

To finish implementing it in FastAPI in the simplest and more convenient way, we depend on a feature of Starlette that will be available soon: encode/starlette#379

Meanwhile, a "hack" to work around it, that is the closest to what we want is described in the updated docs: https://fastapi.tiangolo.com/tutorial/sql-databases/


In short, the situation happens because FastAPI will call the non-async functions in a separate thread, and the scoped_session will create a separate session for each sub-thread, but then it is not being closed properly.

If you don't want to use the technique described in the docs, you can just create a new Session with db_session = Session() at the beginning of each path operation function and call db_session.close() at the end (as you are doing).

For more information, check the comments here: encode/starlette#370 (comment)


This is just an update on the state of it, so you know how to proceed meanwhile, but once we have request.state I'll update the docs accordingly.

from fastapi.

tiangolo avatar tiangolo commented on May 7, 2024 2

So, request.state in Starlette was implemented today: encode/starlette#404

I just updated FastAPI to upgrade the Starlette version (and the compatibility changes).

And I updated the tutorial for SQL with SQLAlchemy using the new request.state: https://fastapi.tiangolo.com/tutorial/sql-databases/

You should now be able to use the new, proper technique, with FastAPI version 0.6.0 πŸŽ‰

from fastapi.

tiangolo avatar tiangolo commented on May 7, 2024 1

The documentation/tutorial for SQLAlchemy was broken, sorry for that πŸ˜₯

It is fixed now, and the code of the tutorial itself is now part of the tests, so it is now continuously ensured that that code works as it should.

The new tutorial doesn't require a full PostgreSQL server, as it uses a SQLite database (a single file), so, you should be able to just copy the code as is, and run it locally, and there you would have a full FastAPI (micro) application, serving from a local database (in a file tests.db).

Please try the new tutorial an let me know how it goes: https://fastapi.tiangolo.com/tutorial/sql-databases/

from fastapi.

euri10 avatar euri10 commented on May 7, 2024 1

from fastapi.

alexiri avatar alexiri commented on May 7, 2024 1

Hola @tiangolo, thanks a lot for this great update, I understand the problem now. I've implemented the hack for now until the final solution is available.

from fastapi.

alexiri avatar alexiri commented on May 7, 2024

Hola @tiangolo,

I must still be doing something wrong, I'm still exhausting the connection pool.

My app.models __init__.py looks like this:

...
engine = create_engine(DATABASE_URI,
    convert_unicode=True,
    echo=False, echo_pool=True,
    pool_size=5,
    max_overflow=0,
    pool_recycle=1)

db_session = scoped_session(
    sessionmaker(autocommit=False, autoflush=False, bind=engine)
)

class CustomBase:
    # Generate __tablename__ automatically
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

Base = declarative_base(cls=CustomBase)
Base.metadata.create_all(bind=engine)

Then, from each place I need a DB connection (like app.crud.user) I do a

from app.models import db_session
...
def get_user_by_id(userid):
    return db_session.query(User).get(userid)

I guess this isn't the right way of doing it, as it seems each import opens a new connection and it never gets released. What should I be doing instead?

from fastapi.

alexiri avatar alexiri commented on May 7, 2024

I'm using Postgres and the error I get is:

sqlalchemy.exc.TimeoutError: QueuePool limit of size 5 overflow 0 reached, connection timed out, timeout 30 (Background on this error at: http://sqlalche.me/e/3o7r)

This happens after 5 queries to the DB, which leads me to believe I'm not liberating connections as I should.

Still, you're right, the easiest way forward is for me to produce a test case. I'll work on that when I have some time.

from fastapi.

euri10 avatar euri10 commented on May 7, 2024

You might want to take a look at this explanation

I also wrote a sample test case with a postgresql db and several engine configs, looping from 6 to 100 times the same route, facing no timeouts, hope it helps

notice that without https://github.com/euri10/fastapi/blob/58628e81efe027afb2e9ec5ae19113f13a35a7a1/tests/test_psql_pool.py#L51 the timeout will occur as expected when the max_overflow + current connections is reached, hence the read above that explains all that better than I could :)

from fastapi.

alexiri avatar alexiri commented on May 7, 2024

I was just putting this together to show the issue I'm having: https://github.com/alexiri/fastapi_hang. I see now that the problem seems to be how I'm using dependencies that also query the database. The reason I'm trying to do that is to create dependencies that verify a user's role to see if they're allowed to perform a particular action, imitating get_current_user in the Security examples.

The issue does go away if I put a db_session.close() after both queries, but then I guess one request opens and closes two DB sessions... I guess I'm going about this all wrong?

from fastapi.

tiangolo avatar tiangolo commented on May 7, 2024

Thanks! πŸ˜„

from fastapi.

github-actions avatar github-actions commented on May 7, 2024

Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs.

from fastapi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.