0

I have created an application using Quart, it has a background task that performs tasks such as data analysis and writing reports. When I end the application with ctrl-c the background thread is instantly killed, even if it's in the middle of an IO task, how do I get the framework to wait for the background task to finish please?

Update: My initial implementation was to use to have run() execute thread, I was trying to get away from this since asyncio supports the creation of tasks (create_task) and it seems like the better way, although I don't honestly know.

class Application:
    def __init__(self):
        self._is_initialised : bool = False
        self._shutdown_completed : bool = False
        self._shutdown_requested : bool = False

    async def run(self) -> None:
        while not self._shutdown_requested and self._is_initialised:
            try:
                await self._main_loop()
                await asyncio.sleep(0.1)

            except KeyboardInterrupt:
                break

        self._shutdown_completed = True

    def stop(self) -> None:
        print("Shutting down...")
        self._shutdown_requested = True
        print('Shutdown has completed')


import asyncio
from quart import Quart

app = Quart(__name__)
SERVICE_APP = None

@app.before_serving
async def startup() -> None:
    asyncio.create_task(SERVICE_APP.run())

@app.after_serving
async def shutdown() -> None:
    SERVICE_APP.stop()

SERVICE_APP = Application(app)
Swatcat
  • 73
  • 6
  • 21
  • 57
  • Does this answer your question? [How to process SIGTERM signal gracefully?](https://stackoverflow.com/questions/18499497/how-to-process-sigterm-signal-gracefully) – Julien Sorin Aug 16 '22 at 10:11
  • @JulienSorin My original implementation used a thread, if that is the only solution where the task waits for completion I will use it, but it seems to go against how asyncio should be used as you can create tasks using the library. – Swatcat Aug 16 '22 at 10:28
  • 1
    Have you tried a background task, https://quart.palletsprojects.com/en/latest/how_to_guides/background_tasks.html? – pgjones Aug 16 '22 at 13:12
  • @pgjones Thank you that worked if you want to make it an answer. I didn't realise this method was still available, I incorrectly assumed it was deprecated a while ago. – Swatcat Aug 16 '22 at 14:50

1 Answers1

1

A background task is likely the better choice here as Quart will delay shutdown (for as long as the ASGI server allows) whilst waiting for the background tasks to stop, see docs:

from quart import Quart

app = Quart(__name__)

async def background_task():
    # Actual code to run in the background

@app.before_serving
async def startup() -> None:
    app.add_background_task(background_task)
pgjones
  • 6,044
  • 1
  • 14
  • 12