question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Does graphene_sqlalchemy keep sessions open?

See original GitHub issue

tl;dr

Does graphene_sqlalchemy keep sessions open? I’m having the problem that Postgres doesnt run drop_all() in my test suite.

Explanation

Hi, I have a fastAPI app and I’m using graphene_sqlalchemy to generate an API from database models defined on the declarative base of SQLAlchemy. The database is postgres. For testing I am running some pytests against the API while it’s running. So, I start a throw-away postgres container, then I start the API app, then I run pytest.

The tests include a reset_testdata() function which also uses the SQLAlchemy ORM. It looks like:

def reset_testdata():
    close_all_sessions()  # from sqlalchemy.orm.session
    models.Base.metadata.drop_all(bind=engine)
    models.Base.metadata.create_all(bind=engine)

    db.add_all([
        # ... add stuff
    ])

    db.commit()
    db.close()

I noticed, that once reset_testdata() is used, the pytest process hangs. No errors, not able to Ctrl+C, it just waits. I had this issue before and it usually stems from Postgres not allowing stuff like drop_all() if there are still active sessions. After some trying out I found that queries from my app (which are implemented by graphene_sqlalchemy) seem to keep a session open. (I used this example in my app: https://docs.graphene-python.org/projects/sqlalchemy/en/latest/tutorial/#defining-our-models)

I tested this, and basically I can circumvent this problem by adding a middleware that closes all sessions after every request.

@app.middleware('http')
async def close_sessions(request: Request, call_next):
    try:
        response = await call_next(request)
    finally:
        close_all_sessions()
    return response

I wonder whether I am missing something here? Any experience with this issue (if it is even an issue)?

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:3
  • Comments:6

github_iconTop GitHub Comments

1reaction
davidroecacommented, Sep 9, 2021

Unfortunately, that renders a lot of graphene-sqlalchemy’s relationship and queries capabilities useless. My preferred approach is closer to this one within a similar thread.

Along the lines of:

from contextvars import ContextVar
import uuid

_request_id_ctx_var = ContextVar('request_id', default=None)
def get_request_id():
    return _request_id_ctx_var.get()

engine = create_engine(SQLALCHEMY_DATABASE_URL)
session = scoped_session(
    sessionmaker(autocommit=False, autoflush=False, bind=engine),
    scopefunc=get_request_id,
)
# ... create Base, as in the example
Base.query = session.query_property()


@api.middleware("http")
async def set_request_id(request, call_next):
    request_id = str(uuid.uuid4())
    ctx_token = _request_id_ctx_var.set(request_id)

    response = await call_next(request)

    _request_id_ctx_var.reset(ctx_token)
    return response
0reactions
davidroecacommented, Sep 16, 2021

@dmitrybabanovforreal did you read this doc (in particular, this section)?

I don’t think avoiding scoped_session is necessarily a “best practice” but rather a recommendation from tiangolo to reduce confusion for new users. In this case, avoiding scoped_session requires you to write resolver functions for every relationship. Using scoped_session in the way SQLAlchemy recommends (one session per request) will enable you to use graphene-sqlalchemy with its original design while not having to write custom code if you don’t have to.

Now, if you’re stuck writing your own resolvers anyway (due to additional custom logic, or something else), then your approach is still a fine solution. The more models/relationships, the more painful it gets though.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Python (Flask) with GraphQL Server implementing ... - Medium
Let's go over GraphQL's types and schemas by creating a small project in Python and Flask web framework (implementing graphene and ...
Read more >
GraphQL Authorization with Graphene, SQLAlchemy and oso
Use oso's policy engine to build an authorization solution that integrates directly with GraphQL, using Graphene, SQLAlchemy, & Flask.
Read more >
Building GraphQL API with Graphene, SQLAlchemy And Flask
In this stream, we are going to build a GraphQL API with Flask and SQLAlchemy, and Graphene.
Read more >
SQLAlchemy - Graphene-Python
SQLAlchemy + Flask Tutorial · Setup the Project · Defining our models · Schema · Creating GraphQL and GraphiQL views in Flask ·...
Read more >
graphene-sqlalchemy-filter - PyPI
This type of filter is the same as simple filters but has a different return type. The filtration function should return a new...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found