Merge pull request #12 from sharelatex/ja-redis-cluster-refactor

Use new redis-sharelatex with support for cluster
This commit is contained in:
James Allen 2017-05-10 15:30:41 +01:00 committed by GitHub
commit b7a07ea1b7
11 changed files with 56 additions and 40 deletions

View file

@ -51,12 +51,14 @@ io.configure ->
app.get "/status", (req, res, next) -> app.get "/status", (req, res, next) ->
res.send "real-time-sharelatex is alive" res.send "real-time-sharelatex is alive"
redisCheck = redis.activeHealthCheckRedis(Settings.redis.web) rclient = require("redis-sharelatex").createClient(Settings.redis.realtime)
app.get "/health_check/redis", (req, res, next) -> app.get "/health_check/redis", (req, res, next) ->
if redisCheck.isAlive() rclient.healthCheck (error) ->
res.send 200 if error?
logger.err {err: error}, "failed redis health check"
res.sendStatus 500
else else
res.send 500 res.sendStatus 200
Router = require "./app/js/Router" Router = require "./app/js/Router"
Router.configure(app, io, sessionSockets) Router.configure(app, io, sessionSockets)

View file

@ -2,8 +2,8 @@ async = require("async")
Settings = require('settings-sharelatex') Settings = require('settings-sharelatex')
logger = require("logger-sharelatex") logger = require("logger-sharelatex")
redis = require("redis-sharelatex") redis = require("redis-sharelatex")
rclient = redis.createClient(Settings.redis.web) rclient = redis.createClient(Settings.redis.realtime)
Keys = Settings.redis.realtime.key_schema
ONE_HOUR_IN_S = 60 * 60 ONE_HOUR_IN_S = 60 * 60
ONE_DAY_IN_S = ONE_HOUR_IN_S * 24 ONE_DAY_IN_S = ONE_HOUR_IN_S * 24
@ -11,10 +11,6 @@ FOUR_DAYS_IN_S = ONE_DAY_IN_S * 4
USER_TIMEOUT_IN_S = ONE_HOUR_IN_S / 4 USER_TIMEOUT_IN_S = ONE_HOUR_IN_S / 4
buildProjectSetKey = (project_id)-> return "clients_in_project:#{project_id}"
buildUserKey = (project_id, client_id)-> return "connected_user:#{project_id}:#{client_id}"
module.exports = module.exports =
# Use the same method for when a user connects, and when a user sends a cursor # Use the same method for when a user connects, and when a user sends a cursor
@ -25,18 +21,18 @@ module.exports =
multi = rclient.multi() multi = rclient.multi()
multi.sadd buildProjectSetKey(project_id), client_id multi.sadd Keys.clientsInProject({project_id}), client_id
multi.expire buildProjectSetKey(project_id), FOUR_DAYS_IN_S multi.expire Keys.clientsInProject({project_id}), FOUR_DAYS_IN_S
multi.hset buildUserKey(project_id, client_id), "last_updated_at", Date.now() multi.hset Keys.connectedUser({project_id, client_id}), "last_updated_at", Date.now()
multi.hset buildUserKey(project_id, client_id), "user_id", user._id multi.hset Keys.connectedUser({project_id, client_id}), "user_id", user._id
multi.hset buildUserKey(project_id, client_id), "first_name", user.first_name or "" multi.hset Keys.connectedUser({project_id, client_id}), "first_name", user.first_name or ""
multi.hset buildUserKey(project_id, client_id), "last_name", user.last_name or "" multi.hset Keys.connectedUser({project_id, client_id}), "last_name", user.last_name or ""
multi.hset buildUserKey(project_id, client_id), "email", user.email or "" multi.hset Keys.connectedUser({project_id, client_id}), "email", user.email or ""
if cursorData? if cursorData?
multi.hset buildUserKey(project_id, client_id), "cursorData", JSON.stringify(cursorData) multi.hset Keys.connectedUser({project_id, client_id}), "cursorData", JSON.stringify(cursorData)
multi.expire buildUserKey(project_id, client_id), USER_TIMEOUT_IN_S multi.expire Keys.connectedUser({project_id, client_id}), USER_TIMEOUT_IN_S
multi.exec (err)-> multi.exec (err)->
if err? if err?
@ -46,14 +42,14 @@ module.exports =
markUserAsDisconnected: (project_id, client_id, callback)-> markUserAsDisconnected: (project_id, client_id, callback)->
logger.log project_id:project_id, client_id:client_id, "marking user as disconnected" logger.log project_id:project_id, client_id:client_id, "marking user as disconnected"
multi = rclient.multi() multi = rclient.multi()
multi.srem buildProjectSetKey(project_id), client_id multi.srem Keys.clientsInProject({project_id}), client_id
multi.expire buildProjectSetKey(project_id), FOUR_DAYS_IN_S multi.expire Keys.clientsInProject({project_id}), FOUR_DAYS_IN_S
multi.del buildUserKey(project_id, client_id) multi.del Keys.connectedUser({project_id, client_id})
multi.exec callback multi.exec callback
_getConnectedUser: (project_id, client_id, callback)-> _getConnectedUser: (project_id, client_id, callback)->
rclient.hgetall buildUserKey(project_id, client_id), (err, result)-> rclient.hgetall Keys.connectedUser({project_id, client_id}), (err, result)->
if !result? if !result?
result = result =
connected : false connected : false
@ -71,7 +67,7 @@ module.exports =
getConnectedUsers: (project_id, callback)-> getConnectedUsers: (project_id, callback)->
self = @ self = @
rclient.smembers buildProjectSetKey(project_id), (err, results)-> rclient.smembers Keys.clientsInProject({project_id}), (err, results)->
return callback(err) if err? return callback(err) if err?
jobs = results.map (client_id)-> jobs = results.map (client_id)->
(cb)-> (cb)->

View file

@ -1,7 +1,7 @@
logger = require "logger-sharelatex" logger = require "logger-sharelatex"
settings = require 'settings-sharelatex' settings = require 'settings-sharelatex'
redis = require("redis-sharelatex") redis = require("redis-sharelatex")
rclient = redis.createClient(settings.redis.web) rclient = redis.createClient(settings.redis.documentupdater)
SafeJsonParse = require "./SafeJsonParse" SafeJsonParse = require "./SafeJsonParse"
MESSAGE_SIZE_LOG_LIMIT = 1024 * 1024 # 1Mb MESSAGE_SIZE_LOG_LIMIT = 1024 * 1024 # 1Mb

View file

@ -3,8 +3,8 @@ logger = require "logger-sharelatex"
settings = require "settings-sharelatex" settings = require "settings-sharelatex"
metrics = require("metrics-sharelatex") metrics = require("metrics-sharelatex")
redis = require("redis-sharelatex") rclient = require("redis-sharelatex").createClient(settings.redis.documentupdater)
rclient = redis.createClient(settings.redis.web) Keys = settings.redis.documentupdater.key_schema
module.exports = DocumentUpdaterManager = module.exports = DocumentUpdaterManager =
getDocument: (project_id, doc_id, fromVersion, callback = (error, exists, doclines, version) ->) -> getDocument: (project_id, doc_id, fromVersion, callback = (error, exists, doclines, version) ->) ->
@ -56,7 +56,7 @@ module.exports = DocumentUpdaterManager =
jsonChange = JSON.stringify change jsonChange = JSON.stringify change
doc_key = "#{project_id}:#{doc_id}" doc_key = "#{project_id}:#{doc_id}"
multi = rclient.multi() multi = rclient.multi()
multi.rpush "PendingUpdates:#{doc_id}", jsonChange multi.rpush Keys.pendingUpdates({doc_id}), jsonChange
multi.sadd "DocsWithPendingUpdates", doc_key multi.sadd "DocsWithPendingUpdates", doc_key
multi.rpush "pending-updates-list", doc_key multi.rpush "pending-updates-list", doc_key
multi.exec (error) -> multi.exec (error) ->

View file

@ -2,8 +2,8 @@ Settings = require 'settings-sharelatex'
logger = require 'logger-sharelatex' logger = require 'logger-sharelatex'
redis = require("redis-sharelatex") redis = require("redis-sharelatex")
SafeJsonParse = require "./SafeJsonParse" SafeJsonParse = require "./SafeJsonParse"
rclientPub = redis.createClient(Settings.redis.web) rclientPub = redis.createClient(Settings.redis.realtime)
rclientSub = redis.createClient(Settings.redis.web) rclientSub = redis.createClient(Settings.redis.realtime)
module.exports = WebsocketLoadBalancer = module.exports = WebsocketLoadBalancer =
rclientPub: rclientPub rclientPub: rclientPub

View file

@ -1,9 +1,19 @@
module.exports = module.exports =
redis: redis:
web: realtime:
host: "localhost" host: "localhost"
port: "6379" port: "6379"
password: "" password: ""
key_schema:
clientsInProject: ({project_id}) -> "clients_in_project:#{project_id}"
connectedUser: ({project_id, client_id})-> "connected_user:#{project_id}:#{client_id}"
documentupdater:
host: "localhost"
port: "6379"
password: ""
key_schema:
pendingUpdates: ({doc_id}) -> "PendingUpdates:#{doc_id}"
internal: internal:
realTime: realTime:

View file

@ -18,7 +18,7 @@
"ioredis": "^2.4.0", "ioredis": "^2.4.0",
"logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#v1.1.0", "logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#v1.1.0",
"metrics-sharelatex": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.4.0", "metrics-sharelatex": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.4.0",
"redis-sharelatex": "0.0.9", "redis-sharelatex": "git+https://github.com/sharelatex/redis-sharelatex.git#v1.0.2",
"request": "~2.34.0", "request": "~2.34.0",
"session.socket.io": "^0.1.6", "session.socket.io": "^0.1.6",
"settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0", "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.0.0",

View file

@ -15,7 +15,10 @@ describe "ConnectedUsersManager", ->
@settings = @settings =
redis: redis:
web:{} realtime:
key_schema:
clientsInProject: ({project_id}) -> "clients_in_project:#{project_id}"
connectedUser: ({project_id, client_id})-> "connected_user:#{project_id}:#{client_id}"
@rClient = @rClient =
auth:-> auth:->
setex:sinon.stub() setex:sinon.stub()

View file

@ -13,10 +13,13 @@ describe "DocumentUpdaterController", ->
@EditorUpdatesController = SandboxedModule.require modulePath, requires: @EditorUpdatesController = SandboxedModule.require modulePath, requires:
"logger-sharelatex": @logger = { error: sinon.stub(), log: sinon.stub() } "logger-sharelatex": @logger = { error: sinon.stub(), log: sinon.stub() }
"settings-sharelatex": @settings = "settings-sharelatex": @settings =
redis: web: {} redis:
documentupdater:
key_schema:
pendingUpdates: ({doc_id}) -> "PendingUpdates:#{doc_id}"
"redis-sharelatex" : "redis-sharelatex" :
createClient: ()=> createClient: () =>
@rclient = {auth:->} @rclient = {}
"./SafeJsonParse": @SafeJsonParse = "./SafeJsonParse": @SafeJsonParse =
parse: (data, cb) => cb null, JSON.parse(data) parse: (data, cb) => cb null, JSON.parse(data)

View file

@ -12,7 +12,9 @@ describe 'DocumentUpdaterManager', ->
@version = 42 @version = 42
@settings = @settings =
apis: documentupdater: url: "http://doc-updater.example.com" apis: documentupdater: url: "http://doc-updater.example.com"
redis: web: {} redis: documentupdater:
key_schema:
pendingUpdates: ({doc_id}) -> "PendingUpdates:#{doc_id}"
@rclient = {auth:->} @rclient = {auth:->}
@DocumentUpdaterManager = SandboxedModule.require modulePath, requires: @DocumentUpdaterManager = SandboxedModule.require modulePath, requires:

View file

@ -5,10 +5,10 @@ modulePath = require('path').join __dirname, '../../../app/js/WebsocketLoadBalan
describe "WebsocketLoadBalancer", -> describe "WebsocketLoadBalancer", ->
beforeEach -> beforeEach ->
@rclient = {}
@WebsocketLoadBalancer = SandboxedModule.require modulePath, requires: @WebsocketLoadBalancer = SandboxedModule.require modulePath, requires:
"redis-sharelatex": "redis-sharelatex":
createClient: () -> createClient: () => @rclient
auth:->
"logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() } "logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() }
"./SafeJsonParse": @SafeJsonParse = "./SafeJsonParse": @SafeJsonParse =
parse: (data, cb) => cb null, JSON.parse(data) parse: (data, cb) => cb null, JSON.parse(data)