From eb9500bb9fcfc5800ecfab5fe3145f89b443b5e3 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 16 Mar 2016 23:15:21 +0100 Subject: [PATCH] Fix redis 2.4 auth support --- lib/individualCommands.js | 19 ++++++++++++++----- test/auth.spec.js | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/individualCommands.js b/lib/individualCommands.js index e4c871842a..188372eea2 100644 --- a/lib/individualCommands.js +++ b/lib/individualCommands.js @@ -4,6 +4,7 @@ var utils = require('./utils'); var debug = require('./debug'); var Multi = require('./multi'); var no_password_is_set = /no password is set/; +var loading = /LOADING/; var RedisClient = require('../').RedisClient; /******************************** @@ -91,12 +92,20 @@ RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, c this.auth_pass = pass; this.ready = this.offline_queue.length === 0; // keep the execution order intakt var tmp = this.send_command('auth', [pass], function (err, res) { - if (err && no_password_is_set.test(err.message)) { - self.warn('Warning: Redis server does not require a password, but a password was supplied.'); - err = null; - res = 'OK'; + if (err) { + if (no_password_is_set.test(err.message)) { + self.warn('Warning: Redis server does not require a password, but a password was supplied.'); + err = null; + res = 'OK'; + } else if (loading.test(err.message)) { + // If redis is still loading the db, it will not authenticate and everything else will fail + debug('Redis still loading, trying to authenticate later'); + setTimeout(function () { + self.auth(pass, callback); + }, 200); + return; + } } - utils.callback_or_emit(self, callback, err, res); }); this.ready = ready; diff --git a/test/auth.spec.js b/test/auth.spec.js index 102bce91f8..de55c3f23c 100644 --- a/test/auth.spec.js +++ b/test/auth.spec.js @@ -45,6 +45,26 @@ describe("client authentication", function () { }); }); + it('support redis 2.4 with retrying auth commands if still loading', function (done) { + if (helper.redisProcess().spawnFailed()) this.skip(); + + client = redis.createClient.apply(null, args); + var time = Date.now(); + client.auth(auth, function (err, res) { + assert.strictEqual('retry worked', res); + assert(Date.now() - time >= 200, 'Time should be above 200 ms (the reconnect time)'); + assert(Date.now() - time < 300, 'Time should be below 300 ms (the reconnect should only take a bit above 200 ms)'); + done(); + }); + var tmp = client.command_queue.get(0).callback; + client.command_queue.get(0).callback = function (err, res) { + client.auth = function (pass, callback) { + callback(null, 'retry worked'); + }; + tmp(new Error('ERR redis is still LOADING')); + }; + }); + it("emits error when auth is bad without callback", function (done) { if (helper.redisProcess().spawnFailed()) this.skip();