You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When running FastAPI in an AWS Lambda environment, the combination of synchronous request handlers and dependencies may delay or (if the Lambda never resumes execution) never execute code after the yield of a dependency.
Making the request handlers and dependency async functions seems to avoid the problem.
I'm creating this discussion in case other people come across the same issue and for consideration during future development. If someone can provide an explanation for why this happens (as an Answer), that would be excellent, but using async seems to be a fine solution for me for now.
Example Code
# This is a much-simplified example. Our real code uses# mangum and a request endpoint with BackgroundTasks.defget_db_bad() ->Iterator[Session]:
db=SessionLocal()
try:
print("Using DB %s", db)
yielddbfinally:
db.close()
print("Closed DB %s", db)
@app.get("/bad")defbad(db=Depends(get_db_bad)):
run_a_query(db)
return {"msg": "a response from /bad"}
asyncdefget_db_good() ->AsyncIterator[Session]:
db=SessionLocal()
try:
print("Using DB %s", db)
yielddbfinally:
db.close()
print("Closed DB %s", db)
@app.get("/good")asyncdefgood(db=Depends(get_db_good)):
run_a_query(db)
return {"msg": "a response from /good"}
Operating System
Linux
Operating System Details
No response
FastAPI Version
0.85.2
Pydantic Version
1.10.12
Python Version
Python 3.11.4
Additional Context
An example of execution logs when it's working correctly:
START RequestId: xxx Version: 1
Using DB <sqlalchemy.orm.session.Session object at 0x7f819e4374d0>
Connection <TracedConnection at 0x7f819988de80 for Connection at 0x7f81996721d0> checked out from pool
Pool pre-ping on connection <pymysql.connections.Connection object at 0x7f81996721d0>
Connection <TracedConnection at 0x7f819988de80 for Connection at 0x7f81996721d0> being returned to pool
Connection <pymysql.connections.Connection object at 0x7f81996721d0> rollback-on-return
Closed DB <sqlalchemy.orm.session.Session object at 0x7f819e4374d0>
END RequestId: xxx
Note that a single DB connection is borrowed and returned to the pool before Lambda freezes or suspends its execution.
An example of execution logs when it's misbehaving; the DB connection would not get returned to the pool, but ones from previous Lambda executions (where they had not been returned) would get returned:
START RequestId: yyy Version: 1
Using DB <sqlalchemy.orm.session.Session object at 0x7f398f526c10>
Created new connection <TracedConnection at 0x7f3990f5a580 for Connection at 0x7f3990eabad0>
Connection <TracedConnection at 0x7f3990f5a580 for Connection at 0x7f3990eabad0> checked out from pool
Connection <pymysql.connections.Connection object at 0x7f3990eabad0> is fresh, skipping pre-ping
(other log messages from processing THIS request)
Connection <TracedConnection at 0x7f398e2565c0 for Connection at 0x7f398f5d6110> being returned to pool
Connection <pymysql.connections.Connection object at 0x7f398f5d6110> rollback-on-return
Connection <TracedConnection at 0x7f398e2565c0 for Connection at 0x7f398f5d6110> being returned to pool
Connection <pymysql.connections.Connection object at 0x7f398f5d6110> rollback-on-return
Closed DB <sqlalchemy.orm.session.Session object at 0x7f3990ca7890>
(other log messages from processing THIS request)
END RequestId: yyy
When this happens, the database may already have closed the connections on the server side and we see ignored errors ("An uncaught exception occurred.") when we attempt to close the connection from the client side:
<sqlalchemy.orm.session.Session object at 0x7f398a4d7950>#7f398a4d7950
Exception: (pymysql.err.InterfaceError) (0, '')
(Background on this error at: https://sqlalche.me/e/14/rvf5)
Connection <pymysql.connections.Connection object at 0x7f64a1c04a10> rollback-on-return
Exception during reset or similar
ERROR sqlalchemy.pool.impl.QueuePool Exception during reset or similar
pymysql.err.OperationalError: (2006, "MySQL server has gone away (SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:2423)'))")
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Description
When running FastAPI in an AWS Lambda environment, the combination of synchronous request handlers and dependencies may delay or (if the Lambda never resumes execution) never execute code after the yield of a dependency.
Making the request handlers and dependency
asyncfunctions seems to avoid the problem.I'm creating this discussion in case other people come across the same issue and for consideration during future development. If someone can provide an explanation for why this happens (as an Answer), that would be excellent, but using
asyncseems to be a fine solution for me for now.Example Code
Operating System
Linux
Operating System Details
No response
FastAPI Version
0.85.2
Pydantic Version
1.10.12
Python Version
Python 3.11.4
Additional Context
An example of execution logs when it's working correctly:
Note that a single DB connection is borrowed and returned to the pool before Lambda freezes or suspends its execution.
An example of execution logs when it's misbehaving; the DB connection would not get returned to the pool, but ones from previous Lambda executions (where they had not been returned) would get returned:
When this happens, the database may already have closed the connections on the server side and we see ignored errors ("An uncaught exception occurred.") when we attempt to close the connection from the client side:
References:
Beta Was this translation helpful? Give feedback.
All reactions