I'm still quite new to websockets and I've been given a problem I'm having a hard time solving.
I need to build a websocket endpoint with FastAPI in which a group of tasks are run asynchronously (to do so I went with trio) with each task returning a json value through the websocket in realtime.
I've managed to meet these requirements, with my code looking like this:
@router.websocket('/stream')
async def runTasks(
websocket: WebSocket
):
# Initialise websocket
await websocket.accept()
while True:
# Receive data
tasks = await websocket.receive_json()
# Run tasks asynchronously (limiting to 10 tasks at a time)
async with trio.open_nursery() as nursery:
limit = trio.CapacityLimiter(10)
for task in tasks:
nursery.start_soon(run_task, limit, task, websocket)
With run_task looking something like this:
async def run_task(limit, task, websocket):
async with limit:
# Complete task / transaction
await websocket.send_json({"placeholder":"data"})
But now, given two scenarios, I'm supposed to cancel/skip the current remaining nursery tasks, but I'm a bit loss as to how I could achieve that.
The two scenarios I'm given are as follows:
Scenario 1: Imagining the endpoint is called when a user presses a button, if the user were to press the button again while some tasks were still running they should be cancelled or skipped and the process should begin anew
Scenario 2: If the websocket were to be closed, the user were to refresh the page, or exit before the completion of the nursery tasks, the remaining tasks should be cancelled or skipped
I'm trying to read more into Python - How to cancel a specific task spawned by a nursery in python-trio but I'm still puzzled as to how I can cancel the previous nursery with cancel scope before entering the new one. Should I create an additional task that watches a variable or something and cancels once it changes? But then I'd have to stop that task once all the other tasks have finished
