-1

I have a python script(server) called main.py which accepts client requests and add data to a Queue. There are few python worker threads which are checking on that queue. If worker is free and queue is not empty, worker takes an element from the queue, process and send response back to client. Clients should wait until a worker perform the task. How can I do this in python? Basically how can I identify to which client I should send back data. What we normally do is return the value from the serve function at main.py using flask.jsonify(). But I cannot do it here because the processing may probably happen at a later time when threads are free.

Worker threads are in another python script. say worker.py

Here is my main.py

from queue import Queue
import flask
import threading

# initialize flask application
app = flask.Flask(__name__)

## Creating pools
workers = Queue(10)
tasks = Queue(10)

taskLock = threading.Lock()

@app.route('/predict', methods=["POST"])
def serve():
    if flask.request.method == "POST":
        if flask.request.files.get('image'):
            tasks.put(flask.request.files["image"].read())

            ??

            return flask.jsonify(("wait..."))




if __name__ == "__main__":
    print("Server is running...")
    app.run(host='0.0.0.0')

worker.py code

class predictThread(threading.Thread):
    def __init__(self, threadID, name, que, lock):
        threading.Thread.__init__(self)
        self.threadID  =threadID
        self.name = name
        self.que = que
        self.lock = lock

    def run(self):
        print("starting " + self.name + " thread")
        work(self.que, self.lock)
        print("Exiting " + self.name + " thread")


def work(que, lock):
    while True:
        if que.empty():
            time.sleep(2)
        else:
            lock.acquire()
            data = que.get()
            lock.release()
            # process data

Assume worker threads are running in workers queue in main.py. I haven't created them yet.

Thamindu DJ
  • 1,679
  • 4
  • 16
  • 29
  • there are 3 ways i can think of. 1) writing to disk and reading from disk, but that can cause race conditions if not managed right. 2) using an external program's queue like rabbitmq, which is good if you are after reliability incase your scripts crash, but requires some setup and might not be easy to debug. 3) using multiprocessing.Pipe check out this answer https://stackoverflow.com/a/43861226/1310093 – Ta946 Apr 07 '19 at 07:03
  • 1
    That's not my problem. My problem is how can I get client url or something like that using flask. Because I have to send data later on. I cannot return them immediately. I edited the question also. – Thamindu DJ Apr 07 '19 at 11:07

1 Answers1

1

What you have here is an asynchronous processing model. You receive some job and process it later. Since the client-server communication is synchronous, you have a few options:

  1. Persist the HTTP connection: Servers will often have a set timeout value e.g 5/10/15 seconds so what you could do is have the client keep the connection alive longer than this default timeout until you've finished running the job and return the response. The caveat here is that the response time is dependent on the number of jobs you have on your queue and it could be minutes/hours before you get to the job specified in the request which would be at the end of the queue but there are ways to get around that e.g by having a single worker per request. (HTTP Persistent Connection)

  2. You could alternatively send back a 202 ACCEPTED response to the client to show that the job has been accepted for processing and have the client poll the server for the status of that job.

If your client is a browser, you could take a look at the Comet web application model which encompasses different approaches for this problem.

Ryan Marvin
  • 141
  • 1
  • 4