From 0a4186e79a8a40bcd90d6938bb073ebb378a4b2b Mon Sep 17 00:00:00 2001 From: Zihua Li Date: Sun, 7 Feb 2016 15:51:17 +0800 Subject: [PATCH] feat(redis): support readonly mode for cluster --- API.md | 1 + lib/redis.js | 5 ++++- lib/redis/event_handler.js | 5 +++++ test/functional/connection.js | 38 ++++++++++++++++++++++++++--------- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/API.md b/API.md index dd407c4f..d4211785 100644 --- a/API.md +++ b/API.md @@ -62,6 +62,7 @@ Creates a Redis instance | [options.keyPrefix] | string | "''" | The prefix to prepend to all keys in a command. ```javascript var redis = new Redis({ lazyConnect: true }); // No attempting to connect to the Redis server here. // Now let's connect to the Redis server redis.get('foo', function () { }); ``` | | [options.retryStrategy] | function | | See "Quick Start" section | | [options.reconnectOnError] | function | | See "Quick Start" section | +| [options.readOnly] | boolean | false | Enable READONLY mode for the connection. Only available for cluster mode. | **Example** ```js diff --git a/lib/redis.js b/lib/redis.js index 994e1e1d..0f064295 100644 --- a/lib/redis.js +++ b/lib/redis.js @@ -72,6 +72,8 @@ var ScanStream = require('./scan_stream'); * ``` * @param {function} [options.retryStrategy] - See "Quick Start" section * @param {function} [options.reconnectOnError] - See "Quick Start" section + * @param {boolean} [options.readOnly=false] - Enable READONLY mode for the connection. + * Only available for cluster mode. * @extends [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter) * @extends Commander * @example @@ -166,7 +168,8 @@ Redis.defaultOptions = { autoResendUnfulfilledCommands: true, lazyConnect: false, keyPrefix: '', - reconnectOnError: null + reconnectOnError: null, + readOnly: false }; Redis.prototype.resetCommandQueue = function () { diff --git a/lib/redis/event_handler.js b/lib/redis/event_handler.js index ccee143e..f47935ea 100644 --- a/lib/redis/event_handler.js +++ b/lib/redis/event_handler.js @@ -128,6 +128,11 @@ exports.readyHandler = function (self) { self.client('setname', self.options.connectionName); } + if (self.options.readOnly) { + debug('set the connection to readonly mode'); + self.readonly(); + } + if (self.prevCondition) { var condition = self.prevCondition; self.prevCondition = null; diff --git a/test/functional/connection.js b/test/functional/connection.js index 997688d2..3d43270c 100644 --- a/test/functional/connection.js +++ b/test/functional/connection.js @@ -142,8 +142,8 @@ describe('connection', function () { describe('connectionName', function () { it('shoud name the connection if options.connectionName is not null', function (done) { var redis = new Redis({ connectionName: 'niceName' }); - redis.once('ready', function() { - redis.client('getname', function(err, res) { + redis.once('ready', function () { + redis.client('getname', function (err, res) { expect(res).to.eql('niceName'); done(); }); @@ -151,23 +151,41 @@ describe('connection', function () { redis.set('foo', 1); }); - it('should set the name before any subscribe command if reconnected', function(done) { + it('should set the name before any subscribe command if reconnected', function (done) { var redis = new Redis({ connectionName: 'niceName' }); - var pub = new Redis(); redis.once('ready', function () { - redis.subscribe('l', function() { + redis.subscribe('l', function () { redis.disconnect(true); - redis.unsubscribe('l', function() { - redis.client('getname', function(err, res) { - expect(res).to.eql('niceName'); - done(); - }); + redis.unsubscribe('l', function () { + redis.client('getname', function (err, res) { + expect(res).to.eql('niceName'); + done(); + }); }); }); }); }); }); + describe('readOnly', function () { + it('shoud send readonly command before other commands', function (done) { + var called = false; + var redis = new Redis({ port: 30001, readOnly: true, showFriendlyErrorStack: true }); + var node = new MockServer(30001, function (argv) { + if (argv[0] === 'readonly') { + called = true; + } else if (argv[0] === 'get' && argv[1] === 'foo') { + expect(called).to.eql(true); + redis.disconnect(); + node.disconnect(function () { + done(); + }); + } + }); + redis.get('foo').catch(function () {}); + }); + }); + describe('autoResendUnfulfilledCommands', function () { it('should resend unfulfilled commands to the correct db when reconnected', function (done) { var redis = new Redis({ db: 3 });