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 CHANGED
@@ -8,7 +8,7 @@ experimental Redis server branches.
8
8
  Install with:
9
9
 
10
10
  npm install redis
11
-
11
+
12
12
  Pieter Noordhuis has provided a binding to the official `hiredis` C library, which is non-blocking and fast. To use `hiredis`, do:
13
13
 
14
14
  npm install hiredis redis
@@ -55,7 +55,7 @@ This will display:
55
55
  2 replies:
56
56
  0: hashtest 1
57
57
  1: hashtest 2
58
- mjr:~/work/node_redis (master)$
58
+ mjr:~/work/node_redis (master)$
59
59
 
60
60
 
61
61
  ## Performance
@@ -98,18 +98,25 @@ Here is an example of passing an array of arguments and a callback:
98
98
  Here is that same call in the second style:
99
99
 
100
100
  client.mset("test keys 1", "test val 1", "test keys 2", "test val 2", function (err, res) {});
101
-
101
+
102
102
  Note that in either form the `callback` is optional:
103
103
 
104
104
  client.set("some key", "some val");
105
105
  client.set(["some other key", "some val"]);
106
106
 
107
+ If the key is missing, reply will be null (probably):
108
+
109
+ client.get("missingkey", function(err, reply) {
110
+ // reply is null when the key is missing
111
+ console.log(reply);
112
+ });
113
+
107
114
  For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)
108
115
 
109
116
  The commands can be specified in uppercase or lowercase for convenience. `client.get()` is the same as `client.GET()`.
110
117
 
111
- Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings,
112
- integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a
118
+ Minimal parsing is done on the replies. Commands that return a single line reply return JavaScript Strings,
119
+ integer replies return JavaScript Numbers, "bulk" replies return node Buffers, and "multi bulk" replies return a
113
120
  JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keyed by the hash keys.
114
121
 
115
122
  # API
@@ -120,8 +127,8 @@ JavaScript Array of node Buffers. `HGETALL` returns an Object with Buffers keye
120
127
 
121
128
  ### "ready"
122
129
 
123
- `client` will emit `ready` a connection is established to the Redis server and the server reports
124
- that it is ready to receive commands. Commands issued before the `ready` event are queued,
130
+ `client` will emit `ready` a connection is established to the Redis server and the server reports
131
+ that it is ready to receive commands. Commands issued before the `ready` event are queued,
125
132
  then replayed just before this event is emitted.
126
133
 
127
134
  ### "connect"
@@ -134,11 +141,11 @@ you are free to try to send commands.
134
141
 
135
142
  `client` will emit `error` when encountering an error connecting to the Redis server.
136
143
 
137
- Note that "error" is a special event type in node. If there are no listeners for an
138
- "error" event, node will exit. This is usually what you want, but it can lead to some
144
+ Note that "error" is a special event type in node. If there are no listeners for an
145
+ "error" event, node will exit. This is usually what you want, but it can lead to some
139
146
  cryptic error messages like this:
140
147
 
141
- mjr:~/work/node_redis (master)$ node example.js
148
+ mjr:~/work/node_redis (master)$ node example.js
142
149
 
143
150
  node.js:50
144
151
  throw e;
@@ -161,7 +168,7 @@ It would be nice to distinguish these two cases.
161
168
 
162
169
  `client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now
163
170
  writable. This event can be used to stream commands in to Redis and adapt to backpressure. Right now,
164
- you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can
171
+ you need to check `client.command_queue.length` to decide when to reduce your send rate. Then you can
165
172
  resume sending when you get `drain`.
166
173
 
167
174
  ### "idle"
@@ -183,13 +190,18 @@ if any of the input arguments to the original command were Buffer objects.
183
190
  This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to
184
191
  every command on a client.
185
192
  * `socket_nodelay`: defaults to `true`. Whether to call setNoDelay() on the TCP stream, which disables the
186
- Nagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the
193
+ Nagle algorithm on the underlying socket. Setting this option to `false` can result in additional throughput at the
187
194
  cost of more latency. Most applications will want this set to `true`.
188
195
  * `no_ready_check`: defaults to `false`. When a connection is established to the Redis server, the server might still
189
- be loading the database from disk. While loading, the server not respond to any commands. To work around this,
196
+ be loading the database from disk. While loading, the server not respond to any commands. To work around this,
190
197
  `node_redis` has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command
191
198
  indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event.
192
199
  Setting `no_ready_check` to `true` will inhibit this check.
200
+ * `enable_offline_queue`: defaults to `true`. By default, if there is no active
201
+ connection to the redis server, commands are added to a queue and are executed
202
+ once the connection has been established. Setting `enable_offline_queue` to
203
+ `false` will disable this feature and the callback will be execute immediately
204
+ with an error, or an error will be thrown if no callback is specified.
193
205
 
194
206
  ```js
195
207
  var redis = require("redis"),
@@ -227,7 +239,7 @@ something like this `Error: Ready check failed: ERR operation not permitted`.
227
239
  Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed.
228
240
  If you want to exit cleanly, call `client.quit()` to send the `QUIT` command after you have handled all replies.
229
241
 
230
- This example closes the connection to the Redis server before the replies have been read. You probably don't
242
+ This example closes the connection to the Redis server before the replies have been read. You probably don't
231
243
  want to do this:
232
244
 
233
245
  ```js
@@ -241,7 +253,7 @@ want to do this:
241
253
  client.end();
242
254
  ```
243
255
 
244
- `client.end()` is useful for timeout cases where something is stuck or taking too long and you want
256
+ `client.end()` is useful for timeout cases where something is stuck or taking too long and you want
245
257
  to start over.
246
258
 
247
259
  ## Friendlier hash commands
@@ -251,7 +263,7 @@ When dealing with hash values, there are a couple of useful exceptions to this.
251
263
 
252
264
  ### client.hgetall(hash)
253
265
 
254
- The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact
266
+ The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact
255
267
  with the responses using JavaScript syntax.
256
268
 
257
269
  Example:
@@ -270,7 +282,7 @@ Output:
270
282
  Multiple values in a hash can be set by supplying an object:
271
283
 
272
284
  client.HMSET(key2, {
273
- "0123456789": "abcdefghij",
285
+ "0123456789": "abcdefghij", // NOTE: the key and value must both be strings
274
286
  "some manner of key": "a type of value"
275
287
  });
276
288
 
@@ -286,7 +298,7 @@ Multiple values may also be set by supplying a list:
286
298
  ## Publish / Subscribe
287
299
 
288
300
  Here is a simple example of the API for publish / subscribe. This program opens two
289
- client connections, subscribes to a channel on one of them, and publishes to that
301
+ client connections, subscribes to a channel on one of them, and publishes to that
290
302
  channel on the other:
291
303
 
292
304
  ```js
@@ -315,7 +327,7 @@ channel on the other:
315
327
  ```
316
328
 
317
329
  When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into "pub/sub" mode.
318
- At that point, only commands that modify the subscription set are valid. When the subscription
330
+ At that point, only commands that modify the subscription set are valid. When the subscription
319
331
  set is empty, the connection is put back into regular mode.
320
332
 
321
333
  If you need to send regular commands to Redis while in pub/sub mode, just open another connection.
@@ -337,23 +349,23 @@ name as `channel`, and the message Buffer as `message`.
337
349
 
338
350
  ### "subscribe" (channel, count)
339
351
 
340
- Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the
352
+ Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the
341
353
  channel name as `channel` and the new count of subscriptions for this client as `count`.
342
354
 
343
- ### "psubscribe" (pattern, count)
355
+ ### "psubscribe" (pattern, count)
344
356
 
345
357
  Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the
346
358
  original pattern as `pattern`, and the new count of subscriptions for this client as `count`.
347
359
 
348
360
  ### "unsubscribe" (channel, count)
349
361
 
350
- Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the
362
+ Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the
351
363
  channel name as `channel` and the new count of subscriptions for this client as `count`. When
352
364
  `count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.
353
365
 
354
366
  ### "punsubscribe" (pattern, count)
355
367
 
356
- Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the
368
+ Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the
357
369
  channel name as `channel` and the new count of subscriptions for this client as `count`. When
358
370
  `count` is 0, this client has left pub/sub mode and no more pub/sub events will be emitted.
359
371
 
@@ -403,7 +415,7 @@ commands while still sending regular client command as in this example:
403
415
  var redis = require("redis"),
404
416
  client = redis.createClient(), multi;
405
417
 
406
- // start a separate multi command queue
418
+ // start a separate multi command queue
407
419
  multi = client.multi();
408
420
  multi.incr("incr thing", redis.print);
409
421
  multi.incr("incr other thing", redis.print);
@@ -423,7 +435,7 @@ commands while still sending regular client command as in this example:
423
435
  });
424
436
  ```
425
437
 
426
- In addition to adding commands to the `MULTI` queue individually, you can also pass an array
438
+ In addition to adding commands to the `MULTI` queue individually, you can also pass an array
427
439
  of commands and arguments to the constructor:
428
440
 
429
441
  ```js
@@ -446,7 +458,7 @@ Redis supports the `MONITOR` command, which lets you see all commands received b
446
458
  across all client connections, including from other client libraries and other computers.
447
459
 
448
460
  After you send the `MONITOR` command, no other commands are valid on that connection. `node_redis`
449
- will emit a `monitor` event for every new monitor message that comes across. The callback for the
461
+ will emit a `monitor` event for every new monitor message that comes across. The callback for the
450
462
  `monitor` event takes a timestamp from the Redis server and an array of command arguments.
451
463
 
452
464
  Here is a simple example:
@@ -470,7 +482,7 @@ Some other things you might like to know about.
470
482
 
471
483
  ## client.server_info
472
484
 
473
- After the ready probe completes, the results from the INFO command are saved in the `client.server_info`
485
+ After the ready probe completes, the results from the INFO command are saved in the `client.server_info`
474
486
  object.
475
487
 
476
488
  The `versions` key contains an array of the elements of the version string for easy comparison.
@@ -518,7 +530,7 @@ Boolean to enable debug mode and protocol tracing.
518
530
 
519
531
  This will display:
520
532
 
521
- mjr:~/work/node_redis (master)$ node ~/example.js
533
+ mjr:~/work/node_redis (master)$ node ~/example.js
522
534
  send command: *3
523
535
  $3
524
536
  SET
@@ -533,7 +545,7 @@ This will display:
533
545
 
534
546
  ## client.send_command(command_name, args, callback)
535
547
 
536
- Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis
548
+ Used internally to send commands to Redis. For convenience, nearly all commands that are published on the Redis
537
549
  Wiki have been added to the `client` object. However, if I missed any, or if new commands are introduced before
538
550
  this library is updated, you can use `send_command()` to send arbitrary commands to Redis.
539
551
 
@@ -545,7 +557,7 @@ Boolean tracking the state of the connection to the Redis server.
545
557
 
546
558
  ## client.command_queue.length
547
559
 
548
- The number of commands that have been sent to the Redis server but not yet replied to. You can use this to
560
+ The number of commands that have been sent to the Redis server but not yet replied to. You can use this to
549
561
  enforce some kind of maximum queue depth for commands while connected.
550
562
 
551
563
  Don't mess with `client.command_queue` though unless you really know what you are doing.
@@ -564,6 +576,34 @@ Current delay in milliseconds before a connection retry will be attempted. This
564
576
  Multiplier for future retry timeouts. This should be larger than 1 to add more time between retries.
565
577
  Defaults to 1.7. The default initial connection retry is 250, so the second retry will be 425, followed by 723.5, etc.
566
578
 
579
+ ### Commands with Optional and Keyword arguments
580
+
581
+ This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation.
582
+
583
+ Example:
584
+ ```js
585
+ var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ];
586
+ client.zadd(args, function (err, response) {
587
+ if (err) throw err;
588
+ console.log('added '+response+' items.');
589
+
590
+ // -Infinity and +Infinity also work
591
+ var args1 = [ 'myzset', '+inf', '-inf' ];
592
+ client.zrevrangebyscore(args1, function (err, response) {
593
+ if (err) throw err;
594
+ console.log('example1', response);
595
+ // write your code here
596
+ });
597
+
598
+ var max = 3, min = 1, offset = 1, count = 2;
599
+ var args2 = [ 'myzset', max, min, 'WITHSCORES', 'LIMIT', offset, count ];
600
+ client.zrevrangebyscore(args2, function (err, response) {
601
+ if (err) throw err;
602
+ console.log('example2', response);
603
+ // write your code here
604
+ });
605
+ });
606
+ ```
567
607
 
568
608
  ## TODO
569
609
 
@@ -575,38 +615,51 @@ Performance can be better for very large values.
575
615
 
576
616
  I think there are more performance improvements left in there for smaller values, especially for large lists of small values.
577
617
 
578
- ## Contributors
618
+ ## How to Contribute
619
+ - open a pull request and then wait for feedback (if
620
+ [DTrejo](http://github.com/dtrejo) does not get back to you within 2 days,
621
+ comment again with indignation!)
579
622
 
623
+ ## Contributors
580
624
  Some people have have added features and fixed bugs in `node_redis` other than me.
581
625
 
582
- In alphabetical order, they are:
583
-
584
- * [Aivo Paas](https://github.com/aivopaas)
585
- * [Andy Ray](https://github.com/DelvarWorld)
586
- * Daniele
587
- * [Dave Hoover](https://github.com/redsquirrel)
588
- * [David Trejo](https://github.com/DTrejo)
589
- * Dayananda Nanjundappa
590
- * [Felix Geisendörfer](https://github.com/felixge)
591
- * [Hank Sims](https://github.com/hanksims)
592
- * [Ian Babrou](https://github.com/bobrik)
593
- * [Isaac Z. Schlueter](https://github.com/isaacs)
594
- * [Louis-Philippe Perron](https://github.com/lp)
595
- * [Maksim Lin](https://github.com/maks)
596
- * [Marcus Westin](https://github.com/marcuswestin)
597
- * [Mark Dawson](https://github.com/markdaws)
598
- * [Nithesh Chandra Gupta Mittapally](https://github.com/nithesh)
599
- * [Orion Henry](https://github.com/orionz)
600
- * [Owen Smith](https://github.com/orls)
601
- * [Paul Carey](https://github.com/paulcarey)
602
- * [Philip Tellis](https://github.com/bluesmoon)
603
- * [Pieter Noordhuis](https://github.com/pietern)
604
- * [Rick Olson](https://github.com/technoweenie)
605
- * [Tim Smart](https://github.com/Tim-Smart)
606
- * [TJ Holowaychuk](https://github.com/visionmedia)
607
- * [Umair Siddique](https://github.com/umairsiddique)
608
- * [Vladimir Dronnikov](https://github.com/dvv)
609
- * [Zachary Scott](https://github.com/zzak)
626
+ Ordered by date of first contribution.
627
+ [Auto-generated](http://github.com/dtrejo/node-authors) on Wed Jul 25 2012 19:14:59 GMT-0700 (PDT).
628
+
629
+ - [Matt Ranney aka `mranney`](https://github.com/mranney)
630
+ - [Tim-Smart aka `tim-smart`](https://github.com/tim-smart)
631
+ - [Tj Holowaychuk aka `visionmedia`](https://github.com/visionmedia)
632
+ - [rick aka `technoweenie`](https://github.com/technoweenie)
633
+ - [Orion Henry aka `orionz`](https://github.com/orionz)
634
+ - [Aivo Paas aka `aivopaas`](https://github.com/aivopaas)
635
+ - [Hank Sims aka `hanksims`](https://github.com/hanksims)
636
+ - [Paul Carey aka `paulcarey`](https://github.com/paulcarey)
637
+ - [Pieter Noordhuis aka `pietern`](https://github.com/pietern)
638
+ - [nithesh aka `nithesh`](https://github.com/nithesh)
639
+ - [Andy Ray aka `andy2ray`](https://github.com/andy2ray)
640
+ - [unknown aka `unknowdna`](https://github.com/unknowdna)
641
+ - [Dave Hoover aka `redsquirrel`](https://github.com/redsquirrel)
642
+ - [Vladimir Dronnikov aka `dvv`](https://github.com/dvv)
643
+ - [Umair Siddique aka `umairsiddique`](https://github.com/umairsiddique)
644
+ - [Louis-Philippe Perron aka `lp`](https://github.com/lp)
645
+ - [Mark Dawson aka `markdaws`](https://github.com/markdaws)
646
+ - [Ian Babrou aka `bobrik`](https://github.com/bobrik)
647
+ - [Felix Geisendörfer aka `felixge`](https://github.com/felixge)
648
+ - [Jean-Hugues Pinson aka `undefined`](https://github.com/undefined)
649
+ - [Maksim Lin aka `maks`](https://github.com/maks)
650
+ - [Owen Smith aka `orls`](https://github.com/orls)
651
+ - [Zachary Scott aka `zzak`](https://github.com/zzak)
652
+ - [TEHEK Firefox aka `TEHEK`](https://github.com/TEHEK)
653
+ - [Isaac Z. Schlueter aka `isaacs`](https://github.com/isaacs)
654
+ - [David Trejo aka `DTrejo`](https://github.com/DTrejo)
655
+ - [Brian Noguchi aka `bnoguchi`](https://github.com/bnoguchi)
656
+ - [Philip Tellis aka `bluesmoon`](https://github.com/bluesmoon)
657
+ - [Marcus Westin aka `marcuswestin2`](https://github.com/marcuswestin2)
658
+ - [Jed Schmidt aka `jed`](https://github.com/jed)
659
+ - [Dave Peticolas aka `jdavisp3`](https://github.com/jdavisp3)
660
+ - [Trae Robrock aka `trobrock`](https://github.com/trobrock)
661
+ - [Shankar Karuppiah aka `shankar0306`](https://github.com/shankar0306)
662
+ - [Ignacio Burgueño aka `ignacio`](https://github.com/ignacio)
610
663
 
611
664
  Thanks.
612
665
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+
3
+ var colors = require('colors'),
4
+ fs = require('fs'),
5
+ _ = require('underscore'),
6
+ metrics = require('metrics'),
7
+
8
+ // `node diff_multi_bench_output.js before.txt after.txt`
9
+ before = process.argv[2],
10
+ after = process.argv[3];
11
+
12
+ if (!before || !after) {
13
+ console.log('Please supply two file arguments:');
14
+ var n = __filename;
15
+ n = n.substring(n.lastIndexOf('/', n.length));
16
+ console.log(' ./' + n + ' multiBenchBefore.txt multiBenchAfter.txt');
17
+ console.log('To generate multiBenchBefore.txt, run');
18
+ console.log(' node multi_bench.js > multiBenchBefore.txt');
19
+ console.log('Thank you for benchmarking responsibly.');
20
+ return;
21
+ }
22
+
23
+ var before_lines = fs.readFileSync(before, 'utf8').split('\n'),
24
+ after_lines = fs.readFileSync(after, 'utf8').split('\n');
25
+
26
+ console.log('Comparing before,', before.green, '(', before_lines.length,
27
+ 'lines)', 'to after,', after.green, '(', after_lines.length, 'lines)');
28
+
29
+ var total_ops = new metrics.Histogram.createUniformHistogram();
30
+
31
+ before_lines.forEach(function(b, i) {
32
+ var a = after_lines[i];
33
+ if (!a || !b || !b.trim() || !a.trim()) {
34
+ // console.log('#ignored#', '>'+a+'<', '>'+b+'<');
35
+ return;
36
+ }
37
+
38
+ b_words = b.split(' ').filter(is_whitespace);
39
+ a_words = a.split(' ').filter(is_whitespace);
40
+
41
+ var ops =
42
+ [b_words, a_words]
43
+ .map(function(words) {
44
+ // console.log(words);
45
+ return parseInt10(words.slice(-2, -1));
46
+ }).filter(function(num) {
47
+ var isNaN = !num && num !== 0;
48
+ return !isNaN;
49
+ });
50
+ if (ops.length != 2) return
51
+
52
+ var delta = ops[1] - ops[0];
53
+
54
+ total_ops.update(delta);
55
+
56
+ delta = humanize_diff(delta);
57
+ console.log(
58
+ // name of test
59
+ command_name(a_words) == command_name(b_words)
60
+ ? command_name(a_words) + ':'
61
+ : '404:',
62
+ // results of test
63
+ ops.join(' -> '), 'ops/sec (∆', delta, ')');
64
+ });
65
+
66
+ console.log('Mean difference in ops/sec:', humanize_diff(total_ops.mean()));
67
+
68
+ function is_whitespace(s) {
69
+ return !!s.trim();
70
+ }
71
+
72
+ function parseInt10(s) {
73
+ return parseInt(s, 10);
74
+ }
75
+
76
+ // green if greater than 0, red otherwise
77
+ function humanize_diff(num) {
78
+ if (num > 0) {
79
+ return ('+' + num).green;
80
+ }
81
+ return ('' + num).red;
82
+ }
83
+
84
+ function command_name(words) {
85
+ var line = words.join(' ');
86
+ return line.substr(0, line.indexOf(','));
87
+ }