Skip to content

Commit

Permalink
more code conventions, expansion of comments, and some addtl error ha…
Browse files Browse the repository at this point in the history
…ndling.
  • Loading branch information
mikermcneil committed Nov 3, 2016
1 parent 40718e6 commit e7a534e
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 98 deletions.
2 changes: 1 addition & 1 deletion lib/configure.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module.exports = function ToConfigure(app) {
// If we see `redis`, change it to `socket.io-redis`.
app.config.sockets.adapter = 'socket.io-redis';
app.log.debug(
'Deprecation warning: In Sails v0.11, Socket.io adapters are now installed '+
'Deprecation warning: In Sails v0.11 and up, Socket.io adapters are now installed '+
'as direct dependencies of your Sails app.'+'\n'+
'You are seeing this message because your Socket.io `adapter` configuration '+
'is no longer supported.'+'\n'+
Expand Down
235 changes: 138 additions & 97 deletions lib/prepare-driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,132 +5,173 @@
var util = require('util');
var path = require('path');
var _ = require('lodash');
var ERRORPACK = require('./errors');



module.exports = function (app){

return function prepareDriver(adapterDef, cb){

var adapterModuleName = adapterDef.moduleName;

// If this is NOT redis, then we're good.
if (adapterDef.moduleName !== 'socket.io-redis') {
return cb();
}

// Otherwise, we're using the socket.io-redis adapter, so
// we've got to do a bit more setup.
// ============================================================
var pathToAdapterDependency = adapterDef.modulePath;
var adapterConfig = adapterDef.config;

// For redis:
// ============================================================
if (adapterModuleName === 'socket.io-redis') {
// Create raw redis clients if necessary
var rawClientsNecessary = adapterConfig.pass || adapterConfig.db || adapterDef.adminBus;
if (!rawClientsNecessary) {
return cb();
}

// Create raw redis clients if necessary
var rawClientsNecessary = adapterConfig.pass || adapterConfig.db || adapterDef.adminBus;
if (!rawClientsNecessary) {
return cb();
}
// Borrow access to the `redis` module from socket.io-redis.
// (this is mainly to ensure a compatible version of the `redis` client library)
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Note that, to use a different Redis client library, you can create two redis client
// instances using your client library of choice, then pass them in as the `pubClient`
// and `subClient` options.
//
// For details on that, see:
// https://github.com/balderdashy/sails-hook-sockets/pull/25#issuecomment-258054197
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var redis;

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// TODO: instead of this auto-requiring stuff, try to extend
// `socket.io-redis` so that it provides public access to its
// internal `redis` client library instance.
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

// NPM 2.x.x
try {
redis = require(path.resolve(pathToAdapterDependency, 'node_modules/redis'));
}
catch (unused) {

// Borrow access to the `redis` module from socket.io-redis
var redis;
// NPM 3.x.x...?
try {
redis = require(path.resolve(pathToAdapterDependency, 'node_modules/redis'));
}
catch (e) {
try {
redis = require('redis');
} catch (e2) {
return cb(e2);
}
redis = require('redis');
} catch (e) {
return cb(e);
}

// Set up object that will be used for redis client options
var redisClientOpts = {};
}//</catch>

// If `pass` was supplied, pass it in as `auth_pass`
if (adapterConfig.pass) {

redisClientOpts.auth_pass = adapterConfig.pass;
}
// Next, set up a dictionary that will be used for redis client options.
var redisClientOpts = {};

// If `pass` was supplied, pass it in as `auth_pass`
if (adapterConfig.pass) {

// Build Redis clients if necessary
if (adapterConfig.pubClient) {
app.log.verbose('adapterConfig.pubClient already specified!! (app running on port %d)', app.config.port);
}
if (adapterConfig.subClient) {
app.log.verbose('adapterConfig.subClient already specified!! (app running on port %d)', app.config.port);
}
adapterConfig.pubClient = adapterConfig.pubClient || redis.createClient(adapterConfig.port || 6379, adapterConfig.host || '127.0.0.1', _.extend({}, redisClientOpts, {
redisClientOpts.auth_pass = adapterConfig.pass;

}//>-


// Build Redis clients if necessary:

// First the pubClient.
if (adapterConfig.pubClient) {
app.log.verbose('custom `pubClient` was provided for the Sails app running on port %d', app.config.port);
}
else {
redis.createClient(adapterConfig.port || 6379, adapterConfig.host || '127.0.0.1', _.extend({}, redisClientOpts, {
return_buffers: true
}));
}//>-

// Then for the subClient.
if (adapterConfig.subClient) {
app.log.verbose('custom `subClient` was provided for the Sails app running on port %d', app.config.port);
}
else {
adapterConfig.subClient = adapterConfig.subClient || redis.createClient(adapterConfig.port || 6379, adapterConfig.host || '127.0.0.1', _.extend({}, redisClientOpts,{
return_buffers: true
}));

// Listen for connection errors from redis clients
// (and handle the first one if necessary)
(function ensureRedisClientsLoadedSuccessfully (done){
var redisClientConnectionError;
var pubReady;
var subReady;
adapterConfig.pubClient.once('ready', function (){
if (pubReady) return;
pubReady = true;
app.log.silly('ad hoc redis client ready (pub) (%d)', app.config.port);
if(!redisClientConnectionError && subReady) {
done();
}
});
adapterConfig.subClient.once('ready', function (){
if (subReady) return;
app.log.silly('ad hoc redis client ready (sub) (%d)', app.config.port);
subReady = true;
if (!redisClientConnectionError && pubReady) {
done();
}
});
adapterConfig.pubClient.on('error', function (err){
app.log.error('Redis error from socket.io->redis client (pub):',err);
// Only care about the first connection error
if (redisClientConnectionError) { return; }
redisClientConnectionError = err;
// If `ready` already fired, just log the error
if (pubReady && subReady) {
return;
}
return done(err);
});
adapterConfig.subClient.on('error', function (err){
app.log.error('Redis error from socket.io->redis client (sub):',err);
// Only care about the first connection error
if (redisClientConnectionError) { return; }
redisClientConnectionError = err;
// If `ready` already fired, just log the error
if (pubReady && subReady) {
return;
}
return done(err);
});
})(function (err){
if (err){
return cb(err);
}//>-


// Now finally, listen for connection errors from redis clients
// (and handle the first one if necessary)
(function ensureRedisClientsLoadedSuccessfully (done){
var redisClientConnectionError;
var pubReady;
var subReady;
adapterConfig.pubClient.once('ready', function (){
if (pubReady) { return; }
pubReady = true;
app.log.silly('ad hoc redis client ready (pub) (%d)', app.config.port);
if(!redisClientConnectionError && subReady) {
done();
}
});
adapterConfig.subClient.once('ready', function (){
if (subReady) { return; }
app.log.silly('ad hoc redis client ready (sub) (%d)', app.config.port);
subReady = true;
if (!redisClientConnectionError && pubReady) {
done();
}
});
adapterConfig.pubClient.on('error', function (err){
app.log.error('Redis error from socket.io->redis client (pub):',err);
// Only care about the first connection error
if (redisClientConnectionError) { return; }
redisClientConnectionError = err;
// If `ready` already fired, just log the error
if (pubReady && subReady) {
return;
}
return done(err);
});
adapterConfig.subClient.on('error', function (err){
app.log.error('Redis error from socket.io->redis client (sub):',err);
// Only care about the first connection error
if (redisClientConnectionError) { return; }
redisClientConnectionError = err;
// If `ready` already fired, just log the error
if (pubReady && subReady) {
return;
}
return done(err);
});
})(function (err){
if (err){ return cb(err); }

// If the `db` option was not specified, then we're done.
if (!adapterConfig.db) {
return cb();
}//--•

// Otherwise, `db` was supplied, so call `select` on that redis database
// from each of our clients.
adapterConfig.pubClient.select(adapterConfig.db, function() {
if (err) { return cb(err); }
// ^^ if this causes problems, it's prbly because Mike added it on Nov 2 for Sails v1.
// It didn't exist before, and there might have been a good reason. But if so, then
// we need to document said reason here (and please ping @mikermcneil about it.)

adapterConfig.subClient.select(adapterConfig.db, function (err){
if (err) { return cb(err); }
// ^^ if this causes problems, it's prbly because Mike added it on Nov 2 for Sails v1.
// It didn't exist before, and there might have been a good reason. But if so, then
// we need to document said reason here (and please ping @mikermcneil about it.)

if (!adapterConfig.db) {
return cb();
}

// if `db` was supplied, call `select` on that redis database
adapterConfig.pubClient.select(adapterConfig.db, function() {
adapterConfig.subClient.select(adapterConfig.db, function (){
return cb();
});
});
});
return;
} // </socket.io-redis>
});//</ subClient.select()>

// Otherwise we're good
else {
return cb();
}
});//</ pubClient.select()>

});//</ ensureRedisClientsLoadedSuccessfully()>

};

Expand Down

0 comments on commit e7a534e

Please sign in to comment.