You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-09 00:22:08 +03:00
Make sure all individual handled command work in multi context the same
Fix quit possibly resulting in reconnections
This commit is contained in:
@@ -291,6 +291,48 @@ describe('client authentication', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('indivdual commands work properly with batch', function (done) {
|
||||
// quit => might return an error instead of "OK" in the exec callback... (if not connected)
|
||||
// auth => might return an error instead of "OK" in the exec callback... (if no password is required / still loading on Redis <= 2.4)
|
||||
// This could be fixed by checking the return value of the callback in the exec callback and
|
||||
// returning the manipulated [error, result] from the callback.
|
||||
// There should be a better solution though
|
||||
|
||||
var args = config.configureClient(parser, 'localhost', {
|
||||
noReadyCheck: true
|
||||
});
|
||||
client = redis.createClient.apply(redis.createClient, args);
|
||||
assert.strictEqual(client.selected_db, undefined);
|
||||
var end = helper.callFuncAfter(done, 8);
|
||||
client.on('monitor', function () {
|
||||
end(); // Should be called for each command after monitor
|
||||
});
|
||||
client.batch()
|
||||
.auth(auth)
|
||||
.SELECT(5, function (err, res) {
|
||||
assert.strictEqual(client.selected_db, 5);
|
||||
assert.strictEqual(res, 'OK');
|
||||
assert.notDeepEqual(client.serverInfo.db5, { avg_ttl: 0, expires: 0, keys: 1 });
|
||||
})
|
||||
.monitor()
|
||||
.set('foo', 'bar', helper.isString('OK'))
|
||||
.INFO(function (err, res) {
|
||||
assert.strictEqual(res.indexOf('# Server\r\nredis_version:'), 0);
|
||||
assert.deepEqual(client.serverInfo.db5, { avg_ttl: 0, expires: 0, keys: 1 });
|
||||
})
|
||||
.get('foo', helper.isString('bar'))
|
||||
.subscribe(['foo', 'bar'])
|
||||
.unsubscribe('foo')
|
||||
.SUBSCRIBE('/foo', helper.isString('/foo'))
|
||||
.psubscribe('*')
|
||||
.quit(helper.isString('OK')) // this might be interesting
|
||||
.exec(function (err, res) {
|
||||
res[4] = res[4].substr(0, 10);
|
||||
assert.deepEqual(res, ['OK', 'OK', 'OK', 'OK', '# Server\r\n', 'bar', 'bar', 'foo', '/foo', '*', 'OK']);
|
||||
end();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -12,8 +12,6 @@ describe("The 'batch' method", function () {
|
||||
describe('using ' + parser + ' and ' + ip, function () {
|
||||
|
||||
describe('when not connected', function () {
|
||||
// TODO: This is somewhat broken and should be fixed in v.3
|
||||
// The commands should return an error instead of returning an empty result
|
||||
var client;
|
||||
|
||||
beforeEach(function (done) {
|
||||
@@ -24,7 +22,7 @@ describe("The 'batch' method", function () {
|
||||
client.on('end', done);
|
||||
});
|
||||
|
||||
it('returns an empty array', function (done) {
|
||||
it('returns an empty array for missing commands', function (done) {
|
||||
var batch = client.batch();
|
||||
batch.exec(function (err, res) {
|
||||
assert.strictEqual(err, null);
|
||||
@@ -33,7 +31,17 @@ describe("The 'batch' method", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an empty array if promisified', function () {
|
||||
it('returns an error for batch with commands', function (done) {
|
||||
var batch = client.batch();
|
||||
batch.set('foo', 'bar');
|
||||
batch.exec(function (err, res) {
|
||||
assert.strictEqual(err, null);
|
||||
assert.strictEqual(res[0].code, 'NR_OFFLINE');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an empty array for missing commands if promisified', function () {
|
||||
return client.batch().execAsync().then(function (res) {
|
||||
assert.strictEqual(res.length, 0);
|
||||
});
|
||||
|
@@ -93,6 +93,27 @@ describe('connection tests', function () {
|
||||
assert.strictEqual(bool, false);
|
||||
});
|
||||
|
||||
it('calling quit while connected without offline queue should end the connection when all commands have finished', function (done) {
|
||||
var called = false;
|
||||
client = redis.createClient({
|
||||
enable_offline_queue: false
|
||||
});
|
||||
client.on('ready', function () {
|
||||
client.set('foo', 'bar', function (err, res) {
|
||||
assert.strictEqual(res, 'OK');
|
||||
called = true;
|
||||
});
|
||||
var bool = client.quit(function (err, res) {
|
||||
assert.strictEqual(res, 'OK');
|
||||
assert.strictEqual(err, null);
|
||||
assert(called);
|
||||
done();
|
||||
});
|
||||
// TODO: In v.3 the quit command would be fired right away, so bool should be true
|
||||
assert.strictEqual(bool, true);
|
||||
});
|
||||
});
|
||||
|
||||
it('do not quit before connected or a connection issue is detected', function (done) {
|
||||
client = redis.createClient();
|
||||
client.set('foo', 'bar', helper.isString('OK'));
|
||||
|
@@ -628,6 +628,40 @@ describe("The 'multi' method", function () {
|
||||
client.stream.destroy();
|
||||
});
|
||||
|
||||
it('indivdual commands work properly with multi', function (done) {
|
||||
// Neither of the following work properly in a transactions:
|
||||
// (This is due to Redis not returning the reply as expected / resulting in undefined behavior)
|
||||
// (Likely there are more commands that do not work with a transaction)
|
||||
//
|
||||
// auth => can't be called after a multi command
|
||||
// monitor => results in faulty return values e.g. multi().monitor().set('foo', 'bar').get('foo')
|
||||
// returns ['OK, 'OK', 'monitor reply'] instead of ['OK', 'OK', 'bar']
|
||||
// quit => ends the connection before the exec
|
||||
// client reply skip|off => results in weird return values. Not sure what exactly happens
|
||||
// subscribe => enters subscribe mode and this does not work in combination with exec (the same for psubscribe, unsubscribe...)
|
||||
//
|
||||
|
||||
assert.strictEqual(client.selected_db, undefined);
|
||||
var multi = client.multi();
|
||||
multi.select(5, function (err, res) {
|
||||
assert.strictEqual(client.selected_db, 5);
|
||||
assert.strictEqual(res, 'OK');
|
||||
assert.notDeepEqual(client.server_info.db5, { avg_ttl: 0, expires: 0, keys: 1 });
|
||||
});
|
||||
// multi.client('reply', 'on', helper.isString('OK')); // Redis v.3.2
|
||||
multi.set('foo', 'bar', helper.isString('OK'));
|
||||
multi.info(function (err, res) {
|
||||
assert.strictEqual(res.indexOf('# Server\r\nredis_version:'), 0);
|
||||
assert.deepEqual(client.server_info.db5, { avg_ttl: 0, expires: 0, keys: 1 });
|
||||
});
|
||||
multi.get('foo', helper.isString('bar'));
|
||||
multi.exec(function (err, res) {
|
||||
res[3] = res[3].substr(0, 10);
|
||||
assert.deepEqual(res, ['OK', 'OK', '# Server\r\n', 'bar']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -618,6 +618,26 @@ describe('The node_redis client', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('monitors reconnects properly and works with the offline queue in a batch statement', function (done) {
|
||||
var i = 0;
|
||||
var multi = client.batch();
|
||||
multi.MONITOR(helper.isString('OK'));
|
||||
multi.mget('hello', 'world');
|
||||
multi.exec(function (err, res) {
|
||||
assert.deepEqual(res, ['OK', [null, null]]);
|
||||
});
|
||||
client.on('monitor', function (time, args, rawOutput) {
|
||||
assert(utils.monitor_regex.test(rawOutput), rawOutput);
|
||||
assert.deepEqual(args, ['mget', 'hello', 'world']);
|
||||
if (i++ === 2) {
|
||||
// End after two reconnects
|
||||
return done();
|
||||
}
|
||||
client.stream.destroy();
|
||||
client.mget('hello', 'world');
|
||||
});
|
||||
});
|
||||
|
||||
it('monitor does not activate if the command could not be processed properly', function (done) {
|
||||
client.MONITOR(function (err, res) {
|
||||
assert.strictEqual(err.code, 'UNCERTAIN_STATE');
|
||||
@@ -748,26 +768,27 @@ describe('The node_redis client', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should fire early', function (done) {
|
||||
client = redis.createClient.apply(null, args);
|
||||
var fired = false;
|
||||
client.info(function (err, res) {
|
||||
fired = true;
|
||||
});
|
||||
client.set('foo', 'bar', function (err, res) {
|
||||
assert(fired);
|
||||
done();
|
||||
});
|
||||
assert.strictEqual(client.offline_queue.length, 1);
|
||||
assert.strictEqual(client.command_queue.length, 1);
|
||||
client.on('connect', function () {
|
||||
assert.strictEqual(client.offline_queue.length, 1);
|
||||
assert.strictEqual(client.command_queue.length, 1);
|
||||
});
|
||||
client.on('ready', function () {
|
||||
assert.strictEqual(client.offline_queue.length, 0);
|
||||
});
|
||||
});
|
||||
// TODO: consider allowing loading commands in v.3
|
||||
// it('should fire early', function (done) {
|
||||
// client = redis.createClient.apply(null, args);
|
||||
// var fired = false;
|
||||
// client.info(function (err, res) {
|
||||
// fired = true;
|
||||
// });
|
||||
// client.set('foo', 'bar', function (err, res) {
|
||||
// assert(fired);
|
||||
// done();
|
||||
// });
|
||||
// assert.strictEqual(client.offline_queue.length, 1);
|
||||
// assert.strictEqual(client.command_queue.length, 1);
|
||||
// client.on('connect', function () {
|
||||
// assert.strictEqual(client.offline_queue.length, 1);
|
||||
// assert.strictEqual(client.command_queue.length, 1);
|
||||
// });
|
||||
// client.on('ready', function () {
|
||||
// assert.strictEqual(client.offline_queue.length, 0);
|
||||
// });
|
||||
// });
|
||||
});
|
||||
|
||||
describe('socket_nodelay', function () {
|
||||
|
Reference in New Issue
Block a user