Whenever I gracefully shut down my FastAPI app by saving a file (with the --reload
option), it waits for all background tasks to be complete before initiating shutdown.
uvicorn INFO: Shutting down
uvicorn INFO: connection closed
uvicorn INFO: Waiting for background tasks to complete. (CTRL+C to force quit)
The problem is that my tasks will never be completed since I need to manually cancel them upon FastAPI shutdown. In the following example:
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup logic (if any)
yield
logger.info("Shutting down sessions")
# Shutdown logic (if any)
Session.close_all()
"Shutting down sessions" is never logged because it is waiting for all background tasks to be completed, which will never happen until I call Session.close_all()
. How am I supposed to close my sessions so that FastAPI can properly shut down?
Referring to Corky's answer here
You can patch Starlette's exit handler to customize its behavior. Since I am using FastAPI
with multiple files I came up with this solution:
from uvicorn.main import Server
from fastapi import FastAPI
....
app = FastAPI()
app.should_exit = False
original_handler = Server.handle_exit
def handle_exit(*args, **kwargs):
app.should_exit = True
original_handler(*args, **kwargs)
Server.handle_exit = handle_exit
Additionally, as you mentioned, you can call Session.close_all()
inside the handle_exit
function.