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/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
- self.send_command(parts[0], [parts[1]]);
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
- queue_len = this.command_queue.getLength();
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. This allows commands like this:
643
- // client.command(arg1, [arg2, arg3, arg4], cb);
644
- // and converts to:
645
- // client.command(arg1, arg2, arg3, arg4, cb);
646
- // which is convenient for some things like sadd
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
- this.offline_queue.push(command_obj);
669
- this.should_buffer = true;
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 Tue Jun 28 2011 22:37:02 GMT-0700 (PDT)
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",
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"