diff --git a/libraries/redis-wrapper/index.coffee b/libraries/redis-wrapper/index.coffee index 8378e47e5d..3b745bd9fa 100644 --- a/libraries/redis-wrapper/index.coffee +++ b/libraries/redis-wrapper/index.coffee @@ -20,6 +20,7 @@ module.exports = RedisSharelatex = client = require("redis").createClient opts.port, opts.host, standardOpts return client + # DO NOT USE. Not robust at all (ends up getting subscribed twice, etc)! createRobustSubscriptionClient: (opts, heartbeatOpts = {}) -> sub = RedisSharelatex.createClient(opts) pub = RedisSharelatex.createClient(opts) @@ -64,6 +65,36 @@ module.exports = RedisSharelatex = , heartbeatInterval return sub + + # Attaches an isAlive() method to the subsciption client which returns true + # so long as we have had a heartbeat recently. + createMonitoredSubscriptionClient: (opts, heartbeatOpts = {}) -> + sub = RedisSharelatex.createClient(opts) + pub = RedisSharelatex.createClient(opts) + + heartbeatInterval = heartbeatOpts.heartbeat_interval or 2000 #ms + isAliveTimeout = heartbeatOpts.is_alive_timeout or 10000 #ms + + id = require("crypto").pseudoRandomBytes(16).toString("hex") + heartbeatChannel = "heartbeat-#{id}" + lastHeartbeat = Date.now() + + sub.subscribe heartbeatChannel, (error) -> + if error? + console.error "ERROR: failed to subscribe to #{heartbeatChannel} channel", error + sub.on "message", (channel, message) -> + if channel == heartbeatChannel + lastHeartbeat = Date.now() + + sub.isAlive = () -> + timeSinceLastHeartbeat = Date.now() - lastHeartbeat + return (timeSinceLastHeartbeat < isAliveTimeout) + + setInterval () -> + pub.publish heartbeatChannel, "PING" + , heartbeatInterval + + return sub