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 :
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'
You don't have to create any rooms to address an individual user. Just set the to argument to the sid of the user you want to address:
emit('my event', my_data, to=user_sid)
The sid value that is assigned to each user is given to you in the connect event handler as request.sid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With