Home > Enterprise >  How to run a background control task inside a Flask app?
How to run a background control task inside a Flask app?

Time:11-12

Context

I am working in an escape game company.

We currently have a Windows app that controls the games :

  • It runs a big loop that checks all the state of all the sensors (via queries to the serial port of the PC), take decisions and sends commands to that same serial port.
  • It has a GUI where the game master can monitor the status of the game and send manual commands to bypass some game logic when needed.

It works very well, but for stability reasons, update nightmare etc, we want to move away from Windows for that specific application. We want to run all this on Linux.

The project

The ideal thing would be a system where the PC that runs the game is headless and the escape room software is remotely controlled using a web interface. This is better that the current situation where the operators have to take remote control of the game PC using Windows Remote Desktop.

I would like to have some kind of RESTful API that can be queried by some JS webpages to display the state of the system and send commands to it.

I have the constrain to do the server part in Python.

But, I don't know how to approach that system.

In one hand, I will have a software that controls real world things and will, obviously, manage only one single game at a given time. Basically a big, non blocking, always running loop.

On the other hand, I will have a REST API to send command to the running game. If I look at web frameworks, such as Flask, it provides RESTful API but it is designed to handle multiple connections at the same time and have them basically isolated from each other.

I don't see how I would make that web part discuss with the game system part.

As you can guess, I am not an expert at all. and I would like to keep the system as simple as possible to keep it manageable and understandable.

What should be the best (in term of simplicity) approach here ?

I tough of having two apps, one that runs the game and the web server, that sends commands and receive status through some sort of inter-process communication. But it looks complicated.

One dream thing would be to be able to have a sort of background task within the Flask framework that is running the game, sending the serial port requests and following the game scrips. At the same time, when REST request are received, the callback function of the request would have access to the variables of the background tasks to gather the status of the game and reply accordingly.

But I have no ideal how to do that. I even don't know what keyword to Google for to have an idea how to do that. Is there a common pattern here that would be so common that is supported by basic frameworks ? Or am I reinventing the wheel ?

CodePudding user response:

To run a permanent background task in the same process as a Flask application, use a threading.Thread running a function with an infinite loop. Communicate through a queue.Queue which is thread-safe.

Note: if scaling past a single process, this would create multiple, separate control tasks which probably isn't desired. Scaling requires an external database or queue and a task framework such as Celery.

Example (based on Flask quickstart and basic thread usage):

from flask import Flask
from queue import Queue, Empty
from threading import Thread
from time import sleep

app = Flask(__name__)
commands = Queue()

def game_loop():
    while True:
        try:
            command = commands.get_nowait()
            print(command)
        except Empty:
            pass
        sleep(5)  # TODO poll other things

Thread(target=game_loop, daemon=True).start()

# Literally the Flask quickstart but pushing to the queue
@app.route("/")
def hello_world():
    commands.put_nowait({ 'action': 'something' })
    return "<p>Hello, World!</p>"
  • Related