I am trying to develop a web application that supports a long task at the backend. I am using flask-socketio
package on my server along with celery. My workflow is following :
- When a client opens the Html page -- I initiate a socket connection to the server which creates a uid for the user and emits it back.
- Now once the user posts a request for the long task -- I schedule it using celery and once finished I need to emit it to the user who posted the request. (I stored the relevant userid in post request)
I have looked at @Miguels's answer for 39423646/flask-socketio-emit-to-specific-user which creates a separate room for each user and then broadcasts the message on that room. But I wanted to ask if there is some other simpler way to do this since it seems inefficient or forced way to do this.
I also came across the nodejs solution (how-to-send-a-message-to-a-particular-client-with-socket-io) which I felt to be a more natural way to accomplish this. Is there a similar solution in python-socketio too?
Update: After some more search I came across the following solution on a github gist. According to this -- ** flash-socketIO already puts all clients in the separate room given by request.sid
**.
I would still wish to discuss other ways to do this. Specifically if the site traffic is quite high -- wouldn't it lead to too many rooms?
Update (2): my current (working) server code which makes use of rooms. This is borrowed and modified from flask-SocketIO celery example
@celery.task(bind=True)
def long_task(self, userid, url):
# LONG TASK
time.sleep(10)
# meta = some result
post(url, json=meta)
# It seems i can't directly emit from celery function so I mimic a post request and emit from that function
return meta
@app.route('/longtask', methods=['POST'])
def longtask():
userid = request.json['userid']
task = long_task.delay(elementid, userid, url_for('event', _external=True))
return jsonify({}), 202
@socketio.on('connect', namespace='/custom')
def events_connect():
userid = str(uuid.uuid4())
session['userid'] = userid
current_app.clients[userid] = request.sid
emit('userid', {'userid': userid})
@app.route('/event/', methods=['POST'])
def event():
userid = request.json['userid']
data = request.json
roomid = app.clients.get(userid)
socketio.emit('celerystatus', data, namespace='/custom', room=roomid)
return 'ok'