WebsocketLoadBalancer.coffee 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. Settings = require 'settings-sharelatex'
  2. logger = require 'logger-sharelatex'
  3. redis = require("redis-sharelatex")
  4. SafeJsonParse = require "./SafeJsonParse"
  5. rclientPub = redis.createClient(Settings.redis.realtime)
  6. rclientSub = redis.createClient(Settings.redis.realtime)
  7. EventLogger = require "./EventLogger"
  8. module.exports = WebsocketLoadBalancer =
  9. rclientPub: rclientPub
  10. rclientSub: rclientSub
  11. emitToRoom: (room_id, message, payload...) ->
  12. if !room_id?
  13. logger.warn {message, payload}, "no room_id provided, ignoring emitToRoom"
  14. return
  15. data = JSON.stringify
  16. room_id: room_id
  17. message: message
  18. payload: payload
  19. logger.log {room_id, message, payload, length: data.length}, "emitting to room"
  20. @rclientPub.publish "editor-events", data
  21. emitToAll: (message, payload...) ->
  22. @emitToRoom "all", message, payload...
  23. listenForEditorEvents: (io) ->
  24. @rclientSub.subscribe "editor-events"
  25. @rclientSub.on "message", (channel, message) ->
  26. EventLogger.debugEvent(channel, message) if Settings.debugEvents > 0
  27. WebsocketLoadBalancer._processEditorEvent io, channel, message
  28. _processEditorEvent: (io, channel, message) ->
  29. SafeJsonParse.parse message, (error, message) ->
  30. if error?
  31. logger.error {err: error, channel}, "error parsing JSON"
  32. return
  33. if message.room_id == "all"
  34. io.sockets.emit(message.message, message.payload...)
  35. else if message.room_id?
  36. if message._id?
  37. status = EventLogger.checkEventOrder("editor-events", message._id, message)
  38. if status is "duplicate"
  39. return # skip duplicate events
  40. # send messages only to unique clients (due to duplicate entries in io.sockets.clients)
  41. clientList = io.sockets.clients(message.room_id)
  42. # avoid unnecessary work if no clients are connected
  43. return if clientList.length is 0
  44. logger.log {channel:channel, message: message.message, room_id: message.room_id, message_id: message._id, socketIoClients: (client.id for client in clientList)}, "distributing event to clients"
  45. seen = {}
  46. for client in clientList when not seen[client.id]
  47. seen[client.id] = true
  48. client.emit(message.message, message.payload...)
  49. else if message.health_check?
  50. logger.debug {message}, "got health check message in editor events channel"