2014-11-13 16:03:37 +00:00
|
|
|
Settings = require 'settings-sharelatex'
|
2014-11-24 12:09:12 +00:00
|
|
|
logger = require 'logger-sharelatex'
|
2019-07-09 10:45:00 +00:00
|
|
|
RedisClientManager = require "./RedisClientManager"
|
2015-12-01 11:05:49 +00:00
|
|
|
SafeJsonParse = require "./SafeJsonParse"
|
2019-03-19 10:55:12 +00:00
|
|
|
EventLogger = require "./EventLogger"
|
2019-04-15 13:05:26 +00:00
|
|
|
HealthCheckManager = require "./HealthCheckManager"
|
2019-07-18 10:25:10 +00:00
|
|
|
RoomManager = require "./RoomManager"
|
|
|
|
ChannelManager = require "./ChannelManager"
|
2014-11-13 16:03:37 +00:00
|
|
|
|
|
|
|
module.exports = WebsocketLoadBalancer =
|
2019-07-09 11:03:13 +00:00
|
|
|
rclientPubList: RedisClientManager.createClientList(Settings.redis.pubsub)
|
2019-07-11 10:10:33 +00:00
|
|
|
rclientSubList: RedisClientManager.createClientList(Settings.redis.pubsub)
|
2014-11-13 16:03:37 +00:00
|
|
|
|
|
|
|
emitToRoom: (room_id, message, payload...) ->
|
2014-11-24 12:09:12 +00:00
|
|
|
if !room_id?
|
2014-11-24 22:28:50 +00:00
|
|
|
logger.warn {message, payload}, "no room_id provided, ignoring emitToRoom"
|
2014-11-24 12:09:12 +00:00
|
|
|
return
|
2015-11-30 15:25:09 +00:00
|
|
|
data = JSON.stringify
|
2014-11-13 16:03:37 +00:00
|
|
|
room_id: room_id
|
|
|
|
message: message
|
|
|
|
payload: payload
|
2015-11-30 15:25:09 +00:00
|
|
|
logger.log {room_id, message, payload, length: data.length}, "emitting to room"
|
2019-07-18 10:25:10 +00:00
|
|
|
|
2019-06-29 11:28:54 +00:00
|
|
|
for rclientPub in @rclientPubList
|
2019-07-18 10:25:10 +00:00
|
|
|
ChannelManager.publish rclientPub, "editor-events", room_id, data
|
2014-11-13 16:03:37 +00:00
|
|
|
|
|
|
|
emitToAll: (message, payload...) ->
|
|
|
|
@emitToRoom "all", message, payload...
|
|
|
|
|
|
|
|
listenForEditorEvents: (io) ->
|
2019-07-09 13:18:39 +00:00
|
|
|
logger.log {rclients: @rclientPubList.length}, "publishing editor events"
|
|
|
|
logger.log {rclients: @rclientSubList.length}, "listening for editor events"
|
2019-06-29 11:28:54 +00:00
|
|
|
for rclientSub in @rclientSubList
|
|
|
|
rclientSub.subscribe "editor-events"
|
|
|
|
rclientSub.on "message", (channel, message) ->
|
|
|
|
EventLogger.debugEvent(channel, message) if Settings.debugEvents > 0
|
|
|
|
WebsocketLoadBalancer._processEditorEvent io, channel, message
|
2019-07-23 16:02:09 +00:00
|
|
|
@handleRoomUpdates(@rclientSubList)
|
2019-07-18 10:25:10 +00:00
|
|
|
|
2019-07-23 16:02:09 +00:00
|
|
|
handleRoomUpdates: (rclientSubList) ->
|
2019-07-18 10:25:10 +00:00
|
|
|
roomEvents = RoomManager.eventSource()
|
|
|
|
roomEvents.on 'project-active', (project_id) ->
|
2019-07-23 16:02:09 +00:00
|
|
|
subscribePromises = for rclient in rclientSubList
|
|
|
|
ChannelManager.subscribe rclient, "editor-events", project_id
|
2019-07-24 13:30:48 +00:00
|
|
|
RoomManager.emitOnCompletion(subscribePromises, "project-subscribed-#{project_id}")
|
2019-07-18 10:25:10 +00:00
|
|
|
roomEvents.on 'project-empty', (project_id) ->
|
2019-07-23 16:02:09 +00:00
|
|
|
for rclient in rclientSubList
|
|
|
|
ChannelManager.unsubscribe rclient, "editor-events", project_id
|
2014-11-13 16:03:37 +00:00
|
|
|
|
|
|
|
_processEditorEvent: (io, channel, message) ->
|
2015-12-01 11:05:49 +00:00
|
|
|
SafeJsonParse.parse message, (error, message) ->
|
|
|
|
if error?
|
|
|
|
logger.error {err: error, channel}, "error parsing JSON"
|
|
|
|
return
|
|
|
|
if message.room_id == "all"
|
|
|
|
io.sockets.emit(message.message, message.payload...)
|
|
|
|
else if message.room_id?
|
2019-07-15 12:45:34 +00:00
|
|
|
if message._id? && Settings.checkEventOrder
|
2019-04-11 11:53:43 +00:00
|
|
|
status = EventLogger.checkEventOrder("editor-events", message._id, message)
|
|
|
|
if status is "duplicate"
|
|
|
|
return # skip duplicate events
|
2019-04-09 13:48:00 +00:00
|
|
|
# send messages only to unique clients (due to duplicate entries in io.sockets.clients)
|
|
|
|
clientList = io.sockets.clients(message.room_id)
|
2019-04-11 11:53:43 +00:00
|
|
|
# avoid unnecessary work if no clients are connected
|
|
|
|
return if clientList.length is 0
|
|
|
|
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"
|
2019-04-09 13:48:00 +00:00
|
|
|
seen = {}
|
|
|
|
for client in clientList when not seen[client.id]
|
|
|
|
seen[client.id] = true
|
|
|
|
client.emit(message.message, message.payload...)
|
2019-02-15 15:23:59 +00:00
|
|
|
else if message.health_check?
|
|
|
|
logger.debug {message}, "got health check message in editor events channel"
|
2019-04-15 13:05:26 +00:00
|
|
|
HealthCheckManager.check channel, message.key
|
2014-11-13 16:03:37 +00:00
|
|
|
|