I am working on a Flask app with a single webpage rendered by the render_template function of Flask. This webpage contains a form to submit data by a post request + WebSocket connection for the status of the task. When the form is submitted, post request for a long-running task is triggered. During the execution of this long-running task, there are few WebSocket messages that are being sent from flask backend to this webpage as the status of the task. However, even though these messages are being sent from backend in proper order, they are only received in the webpage when the long-running task is completed(in other words when the response of form post request is received by webpage). As per my understanding, WebSockets are asynchronous. So why is this happening?
What I am doing:
Post request handler --> websocket msg 1 --> websocket msg2 --> celery --> reponse of post request
I tried adding processes, threads,etc in app.ini.
app.ini for uwsgi
[uwsgi]
module = wsgi:app
master = true
http-socket = 127.0.0.1:7001
gevent = 10
http-websockets = true
nginx config
server {
listen 7000;
server_name _;
location / {
include proxy_params;
proxy_pass http://127.0.0.1:7001;
uwsgi_buffering off;
}
location /socket.io {
include proxy_params;
proxy_http_version 1.1;
uwsgi_buffering off;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:7001/socket.io;
}
}
webpage websocket code
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://' + document.domain + ':' + location.port);
socket.on('connect', function() {
socket.emit('get_status')
socket.emit('get_message')
console.log('Websocket connected!');
});
socket.on('response_status',function(data){
document.getElementById("status").innerHTML = "Status : "+data.status;
console.log("status received");
});
socket.on('response_last_message',function(data){
document.getElementById("message").innerHTML = "Message : "+data.last_message;
console.log("Message received");
});
</script>
Python code:
Main class
socketio = SocketIO()
def create_app():
app = Flask(__name__)
api = Api(app)
socketio.init_app(app)
with open('config.json', 'r') as conf:
configObject = json.load(conf)
commonConfig = commons.Common(configObject)
socketWork = commons.SocketWork(socketio, commonConfig)
api.add_resource(routes.IndexPage,'/', resource_class_kwargs={ 'commonConfig': commonConfig, 'socketWork': socketWork})
api.add_resource(routes.UploadFile, '/uploadFile', resource_class_kwargs={ 'commonConfig': commonConfig, 'socketWork': socketWork})
return app
Socket class
class SocketWork():
def __init__(self, socketio = None, commonObj=None):
self.commonObj = commonObj
self.socketio = socketio
self.socketio.on_event('get_status',self.send_last_status)
self.socketio.on_event('get_message',self.send_last_message)
def send_last_status(self):
print("Send status now")
status = self.commonObj.status
self.socketio.emit("response_status", {"status": status})
def send_last_message(self):
print("Send last message")
msg = self.commonObj.msg
self.socketio.emit("response_last_message", {"last_message": msg})
def send_message(self,msg):
self.commonObj.msg = msg
self.send_last_message()
def send_status(self,statusVal):
self.commonObj.status = statusVal
self.send_last_status()
Long running post method:
class UploadFile(Resource):
def __init__(self, **kwargs):
self.commonConfig = kwargs['commonConfig']
self.socketWork = kwargs['socketWork']
@use_args(args.argsUploadData)
def post(self, args):
msg = "This is socket message"
socketWork.send_message(msg)
socketWork.send_status(commonConfig.config['Status']['READY'])
sleep(15) ###long running task
return constants.generic_msg.PROCESSING_QUERY.name
Expected WebSockets in the webpage to receive messages from flask backend instantaneously but receiving messages after post request is complete. No error message is generated.
from How to fix websocket messages being delayed by Post request in Flask-uwsgi-Nginx setup?
No comments:
Post a Comment