joola.io.engine
Version:
joola.io's Framework Engine
196 lines (179 loc) • 6.54 kB
JavaScript
/**
* joola.io
*
* Copyright Joola Smart Solutions, Ltd. <info@joo.la>
*
* Licensed under GNU General Public License 3.0 or later.
* Some rights reserved. See LICENSE, AUTHORS.
*
* @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>
*/
var redis = function (joola, next) {
joola.redis = {};
joola.redis.online = false;
joola.redis.fake = joola.config.server.redis.fake;
joola.redis.pingTime = 1000;
joola.redis.lostPeerCheckTime = 5000;
if (joola.config.server.redis.DB == null) {
joola.config.server.redis.DB = 0;
}
joola.redis.channelHandlers = {};
var redisPackage;
if (joola.redis.fake == true) {
joola.info("running with fakeredis", "warning");
redisPackage = require('fakeredis');
redisPackage.fast = true;
} else {
redisPackage = require('redis');
}
joola.redis._start = function (joola, next) {
joola.redis.ping(function () {
joola.redis.checkForDroppedPeers(function () {
next();
});
});
};
joola.redis._teardown = function (joola, next) {
joola.redis.stopTimers(joola);
joola.redis.client.lrem("joola:peers", 1, joola.id, function (err, count) {
if (count != 1) {
joola.logger.error("Error removing myself from the peers list");
}
joola.redis.client.hdel("joola:peerPings", joola.id, function () {
next();
});
});
};
joola.redis.initialize = function (callback) {
var started = 0;
['client', 'client-subscriber'].forEach(function (client) {
started++;
joola.redis[client] = redisPackage.createClient(joola.config.server.redis.port, joola.config.server.redis.host, joola.config.server.redis.options || {});
joola.redis[client].on("error", function (err) {
joola.logger.error("Redis Error: " + err);
joola.redis.online = false;
//return callback(err);
//process.exit(); // redis is really important...
});
joola.redis[client].on("connect", function (err) {
if (err)
return callback(err);
joola.logger.silly("client connected to redis [" + client + "] @ " + joola.config.server.redis.host + ":" + joola.config.server.redis.port + " on DB #" + joola.config.server.redis.DB);
joola.redis.online = true;
});
if (joola.config.server.redis.password != null) {
joola.redis[client].auth(joola.config.server.redis.password, function () {
joola.redis[client].select(joola.config.server.redis.DB, function (err) {
if (err) {
//joola.logger.error("Error selecting DB #" + joola.config.server.redis.DB + " on redis.");
return callback(new Error('Failed to select DB #' + joola.config.server.redis.DB + " on redis: " + err));
}
started--;
if (started == 0) {
joola.redis.initPeers(callback);
}
});
});
} else if (joola.config.server.redis.fake != true) {
process.nextTick(function () {
joola.redis[client].select(joola.config.server.redis.DB, function (err) {
if (err) {
//joola.logger.error("Error selecting DB #" + joola.config.server.redis.DB + " on redis.");
return callback(new Error('Failed to select DB #' + joola.config.server.redis.DB + " on redis: " + err));
}
started--;
if (started == 0) {
joola.redis.initPeers(callback);
}
});
});
} else {
process.nextTick(function () {
started--;
if (started == 0) {
joola.redis.initPeers(callback);
}
});
}
});
};
joola.redis.initPeers = function (callback) {
var successMessage = "connected to redis @ " + joola.config.server.redis.host + ":" + joola.config.server.redis.port + " on DB #" + joola.config.server.redis.DB;
if (joola.redis.fake != true) {
joola.redis.client.lrem("joola:peers", 1, joola.id, function () {
joola.redis.client.rpush("joola:peers", joola.id, function () {
joola.logger.info(successMessage);
joola.redis.online = true;
return callback();
});
});
} else {
joola.redis.client.rpush("joola:peers", joola.id, function () {
process.nextTick(function () {
joola.logger.info(successMessage);
joola.redis.online = true;
return callback();
});
});
}
};
joola.redis.stopTimers = function (joola) {
clearTimeout(joola.redis.pingTimer);
clearTimeout(joola.redis.lostPeerTimer);
};
joola.redis.ping = function (next) {
clearTimeout(joola.redis.pingTimer);
joola.redis.client.hset("joola:peerPings", joola.id, new Date().getTime(), function () {
if (joola.running) {
joola.redis.pingTimer = setTimeout(joola.redis.ping, joola.redis.pingTime, joola);
}
if (typeof next == "function") {
next();
}
});
};
joola.redis.checkForDroppedPeers = function (next) {
clearTimeout(joola.redis.lostPeerTimer);
var allowedOffset = ( joola.redis.pingTime * 2 ) + 1;
joola.redis.client.hgetall("joola:peerPings", function (err, peerPings) {
var peerID = null;
for (var i in peerPings) {
if (peerPings.hasOwnProperty(i)) {
if (new Date().getTime() - parseInt(peerPings[i]) > allowedOffset) {
peerID = i;
break; // do one at a time
}
}
}
if (peerID != null) {
joola.logger.error("peer: " + peerID + " has gone away");
joola.redis.client.hdel("joola:peerPings", peerID, function () {
joola.redis.client.lrem("joola:peers", 1, peerID, function () {
if (joola.running) {
joola.redis.lostPeerTimer = setTimeout(joola.redis.checkForDroppedPeers, joola.redis.lostPeerCheckTime, joola);
}
if (typeof next == "function") {
next();
}
});
});
} else {
joola.redis.lostPeerTimer = setTimeout(joola.redis.checkForDroppedPeers, joola.redis.lostPeerCheckTime, joola);
if (typeof next == "function") {
next();
}
}
});
};
joola.redis.flushdb = function (next) {
joola.redis.client.flushdb(function (err) {
next(err);
});
};
joola.redis.initialize(function () {
next();
});
};
/////////////////////////////////////////////////////////////////////
// exports
exports.redis = redis;