Skip to content

Commit

Permalink
Fix the Pub/Sub implementation to fix unit tests and not have a singl…
Browse files Browse the repository at this point in the history
…eton.

Problem:
    The original design of the sentinel with Pub/Sub to the switch-master
    message broke the last unit test because it was always connected to the
    previously successful servers.

Analysis:
    In order to not have always stay connected to the old servers the
    subscription to the Pub/Sub message needs to only occur when the
    successful connect occurs.
  • Loading branch information
ldm5180 committed Nov 20, 2014
1 parent c903a85 commit 942c0ce
Showing 1 changed file with 29 additions and 25 deletions.
54 changes: 29 additions & 25 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function Sentinel(endpoints) {

this.endpoints = endpoints;
this.clients = [];
this.subscribeToSentinelPubSub();
this.pubsub = [];
}

/**
Expand All @@ -21,7 +21,34 @@ function Sentinel(endpoints) {
* @return {RedisClient} the RedisClient for the desired endpoint
*/
Sentinel.prototype.createClient = function(masterName, opts) {
// When the client is ready create another client and subscribe to the
// switch-master event. Then any time there is a message on the channel it
// must be a master change, so reconnect all clients. This avoids combining
// the pub/sub client with the normal client and interfering with whatever
// the user is trying to do.
if (this.pubsub.length == 0) {
var self = this;
var pubsubOpts = {};
pubsubOpts.role = "sentinel";
pubsubClient = this.createClientInternal(masterName, pubsubOpts);
pubsubClient.subscribe("+switch-master", function(error) {
if (error) {
console.error("Unable to subscribe to Sentinel PUBSUB",
host, ":", port);
}
});
pubsubClient.on("message", function(channel, message) {
console.warn("Received +switch-master message from Redis Sentinel.",
" Reconnecting clients.");
self.reconnectAllClients();
});
pubsubClient.on("error", function(error) {});
self.pubsub.push(pubsubClient);
}
return this.createClientInternal(masterName, opts);
}

Sentinel.prototype.createClientInternal = function(masterName, opts) {
if (typeof masterName !== 'string') {
opts = masterName;
masterName = 'mymaster';
Expand Down Expand Up @@ -115,24 +142,6 @@ Sentinel.prototype.createClient = function(masterName, opts) {
return client;
};

/*
* Listen for '+switch-master' events from Sentinel, and reconnect all clients
* when received.
*/
Sentinel.prototype.subscribeToSentinelPubSub = function () {
this.endpoints.forEach(function(endpoint) {
client = redis.createClient(endpoint.port, endpoint.host);
client.subscribe("+switch-master", function(error) {
if (error) {
console.error("Unable to subscribe to Sentinel PUBSUB", endpoint);
}
});
client.on("message", function(channel, message) {
console.warn("Received +switch-master message from Redis Sentinel. Reconnecting clients.");
sentinel.reconnectAllClients();
});
});
}

/*
* Ensure that all clients are trying to reconnect.
Expand Down Expand Up @@ -310,13 +319,8 @@ function parseSentinelResponse(resArr){
}

// Shortcut for quickly getting a client from endpoints
var sentinel = null
function createClient(endpoints, masterName, options) {
if (!sentinel) {
// Only create one global sentinel instance to bind to
// the Sentinel PUBSUB channel.
sentinel = Sentinel(endpoints);
}
var sentinel = Sentinel(endpoints);
return sentinel.createClient(masterName, options);
}

Expand Down

0 comments on commit 942c0ce

Please sign in to comment.