Python Forum

Full Version: Starlette: accumulated tasks. Why?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi everyone!
I have test project:

    from starlette.applications import Starlette
    from starlette.responses import JSONResponse
    from starlette.routing import Route
    
    from starlette.requests import Request
    from starlette.background import BackgroundTasks, BackgroundTask
    
    
    def parse_json(json_data):
        print(json_data['value'])
    
    
    async def testbground(request: Request):
        try:
            json_data = await request.json()
        except JSONDecodeError:
            print('cannot_parse_request_body')
            raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail='cannot_parse_request_body')
        except:
            return JSONResponse({"status": "Error"}, status_code=500)
    
        if 'value' in json_data.keys():
            tasks.add_task(parse_json, json_data)
        else:
            raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail='wrong_json_format')
    
        return JSONResponse({"status": "OK"}, background=tasks, status_code=200)
    
    
    
    
    tasks = BackgroundTasks()
    
    app = Starlette(debug=True, routes=[
        Route('/testbground', endpoint=testbground, methods=['POST']),
    ])
And have sender.py for tests:

    import requests
    
    url = 'http://localhost:8000/testbground'
    
    for i in range(10):
        data = {'value': i}
    
        try:
            r = requests.post(url, json=data, timeout=5)
        except Exception as e:
            print(e)
Result:

Output:
0 0 1 0 1 2 0 1 2 3 ... 0 1 2 3 4 5 6 7 8 9

But I was expecting another result.

Output:
0 1 2 ... 9
What is wrong? How can i add tasks to pull right?
The BackgroundTasks are not deleted when the tasks has been finished, so it's executing all time all existing tasks.

Remove line 32: tasks = BackgroundTasks()

In line 23 replace:
task = BackgroundTask(parse_json, json_data)
# don't forget to import BackgroundTask
# don't use BackgroundTasks

And change
    return JSONResponse({"status": "OK"}, background=tasks, status_code=200)
to
    return JSONResponse({"status": "OK"}, background=task, status_code=200)
Output:
INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: 127.0.0.1:61469 - "POST /testbground HTTP/1.1" 200 OK 5 INFO: 127.0.0.1:61471 - "POST /testbground HTTP/1.1" 200 OK 6 INFO: 127.0.0.1:61474 - "POST /testbground HTTP/1.1" 200 OK 0 INFO: 127.0.0.1:61476 - "POST /testbground HTTP/1.1" 200 OK 1 INFO: 127.0.0.1:61478 - "POST /testbground HTTP/1.1" 200 OK 2 INFO: 127.0.0.1:61480 - "POST /testbground HTTP/1.1" 200 OK 3 INFO: 127.0.0.1:61482 - "POST /testbground HTTP/1.1" 200 OK 4
The implementation of these classes are simple: https://github.com/encode/starlette/blob...ound.py#L7
The Response class takes the background and run it as a coroutine or as a thread if it's not a coroutine.

Why the error happens, is also self-explanatory. In BackgroundTasks class is no automagically method to remove a task.
(Jul-06-2021, 01:56 PM)DeaD_EyE Wrote: [ -> ]The BackgroundTasks are not deleted when the tasks has been finished, so it's executing all time all existing tasks.
Oh! This explains everything. Thanks so much!