4

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 :

  1. 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.
  2. 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'
    


Naman
  • 372
  • 4
  • 20
  • wwhen a client connects save `self` into a static list or dictionary (global) ... then just access that client with `users[client_id].send` (or whatever the method is) – Joran Beasley Mar 13 '21 at 06:16
  • What is self here? I am not using class-based namespaces – Naman Mar 13 '21 at 06:22
  • well you should put you server code ... then someone might be able to help you better ... at least the part that handles newly connecting clients – Joran Beasley Mar 13 '21 at 07:24
  • Oh alright. I'll do that. – Naman Mar 13 '21 at 07:28
  • Does this answer your question? [flask socketio emit to specific user](https://stackoverflow.com/questions/39423646/flask-socketio-emit-to-specific-user) – Loïc Mar 13 '21 at 09:01
  • You can put a list of sid in "room" – Loïc Mar 13 '21 at 09:01
  • Hi, yes I looked at that post and also mentioned it in my question. I found the approach slightly unnatural since if it would lead to a large number of rooms. Therefore I was guessing if there is any other solution. I have modified question to make it more clear – Naman Mar 13 '21 at 09:10

2 Answers2

6

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.

Miguel Grinberg
  • 65,299
  • 14
  • 133
  • 152
-1

You can make a room for every separate user. And you can emit to a particular room which user you want to share the message.

io.to(user.room).emit('specific-user', { message });

Here mean to separate user room that you need to define a room id to a chat room like a chat application (one-to-one-communication). Room id can be concatinate of own id and user id which you want to send a message for a unique room id for each user.

RK NANDA
  • 71
  • 8