redis 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -59
- package/{tests → benches}/buffer_bench.js +0 -0
- package/{tests → benches}/hiredis_parser.js +0 -0
- package/{tests → benches}/re_sub_test.js +0 -0
- package/{tests → benches}/reconnect_test.js +0 -0
- package/{tests → benches}/stress/codec.js +0 -0
- package/{tests → benches}/stress/pubsub/pub.js +0 -0
- package/{tests → benches}/stress/pubsub/run +0 -0
- package/{tests → benches}/stress/pubsub/server.js +0 -0
- package/{tests → benches}/stress/rpushblpop/pub.js +0 -0
- package/{tests → benches}/stress/rpushblpop/run +0 -0
- package/{tests → benches}/stress/rpushblpop/server.js +0 -0
- package/{tests → benches}/stress/speed/00 +0 -0
- package/{tests → benches}/stress/speed/plot +0 -0
- package/{tests → benches}/stress/speed/size-rate.png +0 -0
- package/{tests → benches}/stress/speed/speed.js +0 -0
- package/{tests → benches}/sub_quit_test.js +0 -0
- package/diff_multi_bench_output.js +87 -0
- package/index.js +102 -19
- package/lib/commands.js +22 -1
- package/mem.js +11 -0
- package/package.json +2 -5
- package/test.js +282 -80
package/index.js
CHANGED
|
@@ -5,6 +5,7 @@ var net = require("net"),
|
|
|
5
5
|
Queue = require("./lib/queue"),
|
|
6
6
|
to_array = require("./lib/to_array"),
|
|
7
7
|
events = require("events"),
|
|
8
|
+
crypto = require("crypto"),
|
|
8
9
|
parsers = [], commands,
|
|
9
10
|
connection_id = 0,
|
|
10
11
|
default_port = 6379,
|
|
@@ -50,6 +51,12 @@ function RedisClient(stream, options) {
|
|
|
50
51
|
if (options.connect_timeout && !isNaN(options.connect_timeout) && options.connect_timeout > 0) {
|
|
51
52
|
this.connect_timeout = +options.connect_timeout;
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
this.enable_offline_queue = true;
|
|
56
|
+
if (typeof this.options.enable_offline_queue === "boolean") {
|
|
57
|
+
this.enable_offline_queue = this.options.enable_offline_queue;
|
|
58
|
+
}
|
|
59
|
+
|
|
53
60
|
this.initialize_retry_vars();
|
|
54
61
|
this.pub_sub_mode = false;
|
|
55
62
|
this.subscription_set = {};
|
|
@@ -59,7 +66,9 @@ function RedisClient(stream, options) {
|
|
|
59
66
|
this.auth_pass = null;
|
|
60
67
|
this.parser_module = null;
|
|
61
68
|
this.selected_db = null; // save the selected db here, used when reconnecting
|
|
62
|
-
|
|
69
|
+
|
|
70
|
+
this.old_state = null;
|
|
71
|
+
|
|
63
72
|
var self = this;
|
|
64
73
|
|
|
65
74
|
this.stream.on("connect", function () {
|
|
@@ -266,18 +275,35 @@ RedisClient.prototype.on_ready = function () {
|
|
|
266
275
|
|
|
267
276
|
this.ready = true;
|
|
268
277
|
|
|
278
|
+
if (this.old_state !== null) {
|
|
279
|
+
this.monitoring = this.old_state.monitoring;
|
|
280
|
+
this.pub_sub_mode = this.old_state.pub_sub_mode;
|
|
281
|
+
this.selected_db = this.old_state.selected_db;
|
|
282
|
+
this.old_state = null;
|
|
283
|
+
}
|
|
284
|
+
|
|
269
285
|
// magically restore any modal commands from a previous connection
|
|
270
286
|
if (this.selected_db !== null) {
|
|
271
287
|
this.send_command('select', [this.selected_db]);
|
|
272
288
|
}
|
|
273
289
|
if (this.pub_sub_mode === true) {
|
|
290
|
+
// only emit "ready" when all subscriptions were made again
|
|
291
|
+
var callback_count = 0;
|
|
292
|
+
var callback = function() {
|
|
293
|
+
callback_count--;
|
|
294
|
+
if (callback_count == 0) {
|
|
295
|
+
self.emit("ready");
|
|
296
|
+
}
|
|
297
|
+
}
|
|
274
298
|
Object.keys(this.subscription_set).forEach(function (key) {
|
|
275
299
|
var parts = key.split(" ");
|
|
276
300
|
if (exports.debug_mode) {
|
|
277
301
|
console.warn("sending pub/sub on_ready " + parts[0] + ", " + parts[1]);
|
|
278
302
|
}
|
|
279
|
-
|
|
303
|
+
callback_count++;
|
|
304
|
+
self.send_command(parts[0] + "scribe", [parts[1]], callback);
|
|
280
305
|
});
|
|
306
|
+
return;
|
|
281
307
|
} else if (this.monitoring) {
|
|
282
308
|
this.send_command("monitor");
|
|
283
309
|
} else {
|
|
@@ -376,6 +402,18 @@ RedisClient.prototype.connection_gone = function (why) {
|
|
|
376
402
|
this.connected = false;
|
|
377
403
|
this.ready = false;
|
|
378
404
|
|
|
405
|
+
if (this.old_state === null) {
|
|
406
|
+
var state = {
|
|
407
|
+
monitoring: this.monitoring,
|
|
408
|
+
pub_sub_mode: this.pub_sub_mode,
|
|
409
|
+
selected_db: this.selected_db
|
|
410
|
+
};
|
|
411
|
+
this.old_state = state;
|
|
412
|
+
this.monitoring = false;
|
|
413
|
+
this.pub_sub_mode = false;
|
|
414
|
+
this.selected_db = null;
|
|
415
|
+
}
|
|
416
|
+
|
|
379
417
|
// since we are collapsing end and close, users don't expect to be called twice
|
|
380
418
|
if (! this.emitted_end) {
|
|
381
419
|
this.emit("end");
|
|
@@ -525,8 +563,9 @@ function reply_to_strings(reply) {
|
|
|
525
563
|
|
|
526
564
|
RedisClient.prototype.return_reply = function (reply) {
|
|
527
565
|
var command_obj, obj, i, len, type, timestamp, argindex, args, queue_len;
|
|
528
|
-
|
|
529
|
-
|
|
566
|
+
|
|
567
|
+
command_obj = this.command_queue.shift(),
|
|
568
|
+
queue_len = this.command_queue.getLength();
|
|
530
569
|
|
|
531
570
|
if (this.pub_sub_mode === false && queue_len === 0) {
|
|
532
571
|
this.emit("idle");
|
|
@@ -537,8 +576,6 @@ RedisClient.prototype.return_reply = function (reply) {
|
|
|
537
576
|
this.should_buffer = false;
|
|
538
577
|
}
|
|
539
578
|
|
|
540
|
-
command_obj = this.command_queue.shift();
|
|
541
|
-
|
|
542
579
|
if (command_obj && !command_obj.sub_command) {
|
|
543
580
|
if (typeof command_obj.callback === "function") {
|
|
544
581
|
if (this.options.detect_buffers && command_obj.buffer_args === false) {
|
|
@@ -639,12 +676,11 @@ RedisClient.prototype.send_command = function (command, args, callback) {
|
|
|
639
676
|
throw new Error("send_command: second argument must be an array");
|
|
640
677
|
}
|
|
641
678
|
|
|
642
|
-
// if the last argument is an array, expand it out
|
|
643
|
-
// client.
|
|
644
|
-
//
|
|
645
|
-
// client.
|
|
646
|
-
|
|
647
|
-
if (args.length > 0 && Array.isArray(args[args.length - 1])) {
|
|
679
|
+
// if the last argument is an array and command is sadd, expand it out:
|
|
680
|
+
// client.sadd(arg1, [arg2, arg3, arg4], cb);
|
|
681
|
+
// converts to:
|
|
682
|
+
// client.sadd(arg1, arg2, arg3, arg4, cb);
|
|
683
|
+
if ((command === 'sadd' || command === 'SADD') && args.length > 0 && Array.isArray(args[args.length - 1])) {
|
|
648
684
|
args = args.slice(0, -1).concat(args[args.length - 1]);
|
|
649
685
|
}
|
|
650
686
|
|
|
@@ -662,11 +698,23 @@ RedisClient.prototype.send_command = function (command, args, callback) {
|
|
|
662
698
|
if (!stream.writable) {
|
|
663
699
|
console.log("send command: stream is not writeable.");
|
|
664
700
|
}
|
|
665
|
-
|
|
666
|
-
console.log("Queueing " + command + " for next server connection.");
|
|
667
701
|
}
|
|
668
|
-
|
|
669
|
-
this.
|
|
702
|
+
|
|
703
|
+
if (this.enable_offline_queue) {
|
|
704
|
+
if (exports.debug_mode) {
|
|
705
|
+
console.log("Queueing " + command + " for next server connection.");
|
|
706
|
+
}
|
|
707
|
+
this.offline_queue.push(command_obj);
|
|
708
|
+
this.should_buffer = true;
|
|
709
|
+
} else {
|
|
710
|
+
var not_writeable_error = new Error('send_command: stream not writeable. enable_offline_queue is false');
|
|
711
|
+
if (command_obj.callback) {
|
|
712
|
+
command_obj.callback(not_writeable_error);
|
|
713
|
+
} else {
|
|
714
|
+
throw not_writeable_error;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
670
718
|
return false;
|
|
671
719
|
}
|
|
672
720
|
|
|
@@ -746,7 +794,7 @@ RedisClient.prototype.send_command = function (command, args, callback) {
|
|
|
746
794
|
|
|
747
795
|
RedisClient.prototype.pub_sub_command = function (command_obj) {
|
|
748
796
|
var i, key, command, args;
|
|
749
|
-
|
|
797
|
+
|
|
750
798
|
if (this.pub_sub_mode === false && exports.debug_mode) {
|
|
751
799
|
console.log("Entering pub/sub mode from " + command_obj.command);
|
|
752
800
|
}
|
|
@@ -796,7 +844,7 @@ exports.Multi = Multi;
|
|
|
796
844
|
// take 2 arrays and return the union of their elements
|
|
797
845
|
function set_union(seta, setb) {
|
|
798
846
|
var obj = {};
|
|
799
|
-
|
|
847
|
+
|
|
800
848
|
seta.forEach(function (val) {
|
|
801
849
|
obj[val] = true;
|
|
802
850
|
});
|
|
@@ -898,6 +946,11 @@ RedisClient.prototype.hmset = function (args, callback) {
|
|
|
898
946
|
for (i = 0, il = tmp_keys.length; i < il ; i++) {
|
|
899
947
|
key = tmp_keys[i];
|
|
900
948
|
tmp_args.push(key);
|
|
949
|
+
if (typeof args[1][key] !== "string") {
|
|
950
|
+
var err = new Error("hmset expected value to be a string", key, ":", args[1][key]);
|
|
951
|
+
if (callback) return callback(err);
|
|
952
|
+
else throw err;
|
|
953
|
+
}
|
|
901
954
|
tmp_args.push(args[1][key]);
|
|
902
955
|
}
|
|
903
956
|
args = tmp_args;
|
|
@@ -943,7 +996,7 @@ Multi.prototype.exec = function (callback) {
|
|
|
943
996
|
if (args.length === 1 && Array.isArray(args[0])) {
|
|
944
997
|
args = args[0];
|
|
945
998
|
}
|
|
946
|
-
if (command === 'hmset' && typeof args[1] === 'object') {
|
|
999
|
+
if (command.toLowerCase() === 'hmset' && typeof args[1] === 'object') {
|
|
947
1000
|
obj = args.pop();
|
|
948
1001
|
Object.keys(obj).forEach(function (key) {
|
|
949
1002
|
args.push(key);
|
|
@@ -1006,6 +1059,36 @@ RedisClient.prototype.MULTI = function (args) {
|
|
|
1006
1059
|
return new Multi(this, args);
|
|
1007
1060
|
};
|
|
1008
1061
|
|
|
1062
|
+
|
|
1063
|
+
// stash original eval method
|
|
1064
|
+
var eval = RedisClient.prototype.eval;
|
|
1065
|
+
// hook eval with an attempt to evalsha for cached scripts
|
|
1066
|
+
RedisClient.prototype.eval =
|
|
1067
|
+
RedisClient.prototype.EVAL = function () {
|
|
1068
|
+
var self = this,
|
|
1069
|
+
args = to_array(arguments),
|
|
1070
|
+
callback;
|
|
1071
|
+
|
|
1072
|
+
if (typeof args[args.length - 1] === "function") {
|
|
1073
|
+
callback = args.pop();
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
// replace script source with sha value
|
|
1077
|
+
var source = args[0];
|
|
1078
|
+
args[0] = crypto.createHash("sha1").update(source).digest("hex");
|
|
1079
|
+
|
|
1080
|
+
self.evalsha(args, function (err, reply) {
|
|
1081
|
+
if (err && /NOSCRIPT/.test(err.message)) {
|
|
1082
|
+
args[0] = source;
|
|
1083
|
+
eval.call(self, args, callback);
|
|
1084
|
+
|
|
1085
|
+
} else if (callback) {
|
|
1086
|
+
callback(err, reply);
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
};
|
|
1090
|
+
|
|
1091
|
+
|
|
1009
1092
|
exports.createClient = function (port_arg, host_arg, options) {
|
|
1010
1093
|
var port = port_arg || default_port,
|
|
1011
1094
|
host = host_arg || default_host,
|
package/lib/commands.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
// This file was generated by ./generate_commands.js on
|
|
1
|
+
// This file was generated by ./generate_commands.js on Mon Aug 06 2012 15:04:06 GMT-0700 (PDT)
|
|
2
2
|
module.exports = [
|
|
3
3
|
"append",
|
|
4
4
|
"auth",
|
|
5
5
|
"bgrewriteaof",
|
|
6
6
|
"bgsave",
|
|
7
|
+
"bitcount",
|
|
8
|
+
"bitop",
|
|
7
9
|
"blpop",
|
|
8
10
|
"brpop",
|
|
9
11
|
"brpoplpush",
|
|
12
|
+
"client kill",
|
|
13
|
+
"client list",
|
|
10
14
|
"config get",
|
|
11
15
|
"config set",
|
|
12
16
|
"config resetstat",
|
|
@@ -17,7 +21,10 @@ module.exports = [
|
|
|
17
21
|
"decrby",
|
|
18
22
|
"del",
|
|
19
23
|
"discard",
|
|
24
|
+
"dump",
|
|
20
25
|
"echo",
|
|
26
|
+
"eval",
|
|
27
|
+
"evalsha",
|
|
21
28
|
"exec",
|
|
22
29
|
"exists",
|
|
23
30
|
"expire",
|
|
@@ -33,6 +40,7 @@ module.exports = [
|
|
|
33
40
|
"hget",
|
|
34
41
|
"hgetall",
|
|
35
42
|
"hincrby",
|
|
43
|
+
"hincrbyfloat",
|
|
36
44
|
"hkeys",
|
|
37
45
|
"hlen",
|
|
38
46
|
"hmget",
|
|
@@ -42,6 +50,7 @@ module.exports = [
|
|
|
42
50
|
"hvals",
|
|
43
51
|
"incr",
|
|
44
52
|
"incrby",
|
|
53
|
+
"incrbyfloat",
|
|
45
54
|
"info",
|
|
46
55
|
"keys",
|
|
47
56
|
"lastsave",
|
|
@@ -56,6 +65,7 @@ module.exports = [
|
|
|
56
65
|
"lset",
|
|
57
66
|
"ltrim",
|
|
58
67
|
"mget",
|
|
68
|
+
"migrate",
|
|
59
69
|
"monitor",
|
|
60
70
|
"move",
|
|
61
71
|
"mset",
|
|
@@ -63,14 +73,19 @@ module.exports = [
|
|
|
63
73
|
"multi",
|
|
64
74
|
"object",
|
|
65
75
|
"persist",
|
|
76
|
+
"pexpire",
|
|
77
|
+
"pexpireat",
|
|
66
78
|
"ping",
|
|
79
|
+
"psetex",
|
|
67
80
|
"psubscribe",
|
|
81
|
+
"pttl",
|
|
68
82
|
"publish",
|
|
69
83
|
"punsubscribe",
|
|
70
84
|
"quit",
|
|
71
85
|
"randomkey",
|
|
72
86
|
"rename",
|
|
73
87
|
"renamenx",
|
|
88
|
+
"restore",
|
|
74
89
|
"rpop",
|
|
75
90
|
"rpoplpush",
|
|
76
91
|
"rpush",
|
|
@@ -78,6 +93,10 @@ module.exports = [
|
|
|
78
93
|
"sadd",
|
|
79
94
|
"save",
|
|
80
95
|
"scard",
|
|
96
|
+
"script exists",
|
|
97
|
+
"script flush",
|
|
98
|
+
"script kill",
|
|
99
|
+
"script load",
|
|
81
100
|
"sdiff",
|
|
82
101
|
"sdiffstore",
|
|
83
102
|
"select",
|
|
@@ -91,6 +110,7 @@ module.exports = [
|
|
|
91
110
|
"sinterstore",
|
|
92
111
|
"sismember",
|
|
93
112
|
"slaveof",
|
|
113
|
+
"slowlog",
|
|
94
114
|
"smembers",
|
|
95
115
|
"smove",
|
|
96
116
|
"sort",
|
|
@@ -102,6 +122,7 @@ module.exports = [
|
|
|
102
122
|
"sunion",
|
|
103
123
|
"sunionstore",
|
|
104
124
|
"sync",
|
|
125
|
+
"time",
|
|
105
126
|
"ttl",
|
|
106
127
|
"type",
|
|
107
128
|
"unsubscribe",
|
package/mem.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var client = require("redis").createClient();
|
|
2
|
+
|
|
3
|
+
client.set("foo", "barvalskdjlksdjflkdsjflksdjdflkdsjflksdjflksdj", function (err, res) {
|
|
4
|
+
if (err) {
|
|
5
|
+
console.log("Got an error, please adapt somehow.");
|
|
6
|
+
} else {
|
|
7
|
+
console.log("Got a result: " + res);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
client.quit();
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{ "name" : "redis",
|
|
2
|
-
"version" : "0.7.
|
|
2
|
+
"version" : "0.7.3",
|
|
3
3
|
"description" : "Redis client library",
|
|
4
4
|
"author": "Matt Ranney <mjr@ranney.com>",
|
|
5
|
-
"maintainers": [
|
|
5
|
+
"maintainers": [
|
|
6
6
|
"David Trejo <david.daniel.trejo@gmail.com> (http://dtrejo.com/)"
|
|
7
7
|
],
|
|
8
8
|
"main": "./index.js",
|
|
@@ -12,9 +12,6 @@
|
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"metrics": ">=0.1.5"
|
|
14
14
|
},
|
|
15
|
-
"optionalDependencies": {
|
|
16
|
-
"hiredis": "*"
|
|
17
|
-
},
|
|
18
15
|
"repository": {
|
|
19
16
|
"type": "git",
|
|
20
17
|
"url": "git://github.com/mranney/node_redis.git"
|