Issue
Given this sample Starlette app with an open websocket connection, how do you shut down the Starlette app? I am running on uvicorn. Whenever I press Ctrl+C
the output is Waiting for background tasks to complete.
which hangs forever.
from starlette.applications import Starlette
app = Starlette()
@app.websocket_route('/ws')
async def ws(websocket):
await websocket.accept()
while True:
# How to interrupt this while loop on the shutdown event?
await asyncio.sleep(0.1)
await websocket.close()
I tried switching a bool variable on the shutdown event but the variable never updates. It is always False
.
eg.
app.state.is_shutting_down = False
@app.on_event('shutdown')
async def shutdown():
app.state.is_shutting_down = True
@app.websocket_route('/ws')
async def ws(websocket):
await websocket.accept()
while app.state.is_shutting_down is False:
Solution
The reason your variable didn't change is because the handlers for the "shutdown" event are executed after all the tasks have been executed (i.e. you infinite loop).
Setting a signal handler on the asyncio event loop will probably not work as I believe only a single signal handler is allowed which uvicorn already sets for its own shutdown process.
Instead, you can Monkey Patch the uvicorn signal handler to detect the application shutdown and set your controlling variable in that new function.
import asyncio
from starlette.applications import Starlette
from uvicorn.main import Server
original_handler = Server.handle_exit
class AppStatus:
should_exit = False
@staticmethod
def handle_exit(*args, **kwargs):
AppStatus.should_exit = True
original_handler(*args, **kwargs)
Server.handle_exit = AppStatus.handle_exit
app = Starlette()
@app.websocket_route('/ws')
async def ws(websocket):
await websocket.accept()
while AppStatus.should_exit is False:
await asyncio.sleep(0.1)
await websocket.close()
print('Exited!')
Answered By - Corky
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.