Estoy tratando de desarrollar una aplicación web que admita una tarea larga en el backend. Estoy usando el paquete flask-socketio en mi servidor junto con apio. Mi flujo de trabajo es el siguiente:

  1. Cuando un cliente abre la página Html, inicio una conexión de socket al servidor que crea un uid para el usuario y lo emite de vuelta.
  2. Ahora, una vez que el usuario publica una solicitud para la tarea larga, la programo usando apio y, una vez terminado, necesito emitirla al usuario que publicó la solicitud. (Guardé el ID de usuario relevante en la solicitud de publicación)

He visto la respuesta de @ Miguels para 39423646 / flask-socketio-emit-to-specific- usuario que crea una sala separada para cada usuario y luego transmite el mensaje en esa sala. Pero quería preguntar si hay alguna otra forma más sencilla de hacer esto, ya que parece una forma ineficiente o forzada de hacerlo.

También encontré la solución nodejs (cómo-enviar-un-mensaje-a-un-cliente-particular-con-socket-io) que sentí que era una forma más natural de lograr esto. ¿También hay una solución similar en python-socketio?


Actualización : después de buscar más, encontré la siguiente solución < / a> en una esencia de github. De acuerdo con esto - ** flash-socketIO ya coloca a todos los clientes en la habitación separada dada por request.sid **.

Todavía me gustaría discutir otras formas de hacer esto. Específicamente, si el tráfico del sitio es bastante alto, ¿no generaría demasiadas salas?


Actualización (2) : mi código de servidor actual (en funcionamiento) que hace uso de salas . Esto se tomó prestado y se modificó de ejemplo de apio de flask-SocketIO

@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'
    


1
Naman 13 mar. 2021 a las 09:00

2 respuestas

La mejor respuesta

No es necesario crear salas para dirigirse a un usuario individual. Simplemente establezca el argumento to en el sid del usuario al que desea dirigirse:

emit('my event', my_data, to=user_sid)

El valor de sid que se asigna a cada usuario se le proporciona en el controlador de eventos connect como request.sid.

1
Miguel 14 mar. 2021 a las 10:50

Puede crear una habitación para cada usuario por separado. Y puede emitir a una habitación en particular qué usuario desea compartir el mensaje.

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

Aquí, para separar la sala de usuarios, debe definir una identificación de sala para una sala de chat como una aplicación de chat (comunicación uno a uno). La identificación de la habitación puede ser concatenada por su propia identificación y la identificación de usuario, a la que desea enviar un mensaje para una identificación de sala única para cada usuario.

-1
RK NANDA 13 mar. 2021 a las 08:50