redis 2.6.4 → 2.8.0

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
@@ -6,7 +6,8 @@ redis - a node.js redis client
6
6
  [![Windows Tests](https://img.shields.io/appveyor/ci/BridgeAR/node-redis/master.svg?label=Windows%20Tests)](https://ci.appveyor.com/project/BridgeAR/node-redis/branch/master)
7
7
  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NodeRedis/node_redis?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
8
8
 
9
- This is a complete and feature rich Redis client for node.js. __It supports all Redis commands__ and focuses on high performance.
9
+ This is a complete and feature rich Redis client for node.js. __It supports all
10
+ Redis commands__ and focuses on high performance.
10
11
 
11
12
  Install with:
12
13
 
@@ -48,13 +49,16 @@ This will display:
48
49
  1: hashtest 2
49
50
  mjr:~/work/node_redis (master)$
50
51
 
51
- Note that the API is entirely asynchronous. To get data back from the server, you'll need to use a callback.
52
- From v.2.6 on the API supports camelCase and snake_case and all options / variables / events etc. can be used either way.
53
- It is recommended to use camelCase as this is the default for the Node.js landscape.
52
+ Note that the API is entirely asynchronous. To get data back from the server,
53
+ you'll need to use a callback. From v.2.6 on the API supports camelCase and
54
+ snake_case and all options / variables / events etc. can be used either way. It
55
+ is recommended to use camelCase as this is the default for the Node.js
56
+ landscape.
54
57
 
55
58
  ### Promises
56
59
 
57
- You can also use node_redis with promises by promisifying node_redis with [bluebird](https://github.com/petkaantonov/bluebird) as in:
60
+ You can also use node_redis with promises by promisifying node_redis with
61
+ [bluebird](https://github.com/petkaantonov/bluebird) as in:
58
62
 
59
63
  ```js
60
64
  var redis = require('redis');
@@ -100,7 +104,8 @@ client.set("some key", "some val");
100
104
  client.set(["some other key", "some val"]);
101
105
  ```
102
106
 
103
- If the key is missing, reply will be null. Only if the [Redis Command Reference](http://redis.io/commands) states something else it will not be null.
107
+ If the key is missing, reply will be null. Only if the [Redis Command
108
+ Reference](http://redis.io/commands) states something else it will not be null.
104
109
 
105
110
  ```js
106
111
  client.get("missingkey", function(err, reply) {
@@ -111,8 +116,24 @@ client.get("missingkey", function(err, reply) {
111
116
 
112
117
  For a list of Redis commands, see [Redis Command Reference](http://redis.io/commands)
113
118
 
114
- Minimal parsing is done on the replies. Commands that return a integer return JavaScript Numbers, arrays return JavaScript Array. `HGETALL` returns an Object keyed by the hash keys. All strings will either be returned as string or as buffer depending on your setting.
115
- Please be aware that sending null, undefined and Boolean values will result in the value coerced to a string!
119
+ Minimal parsing is done on the replies. Commands that return a integer return
120
+ JavaScript Numbers, arrays return JavaScript Array. `HGETALL` returns an Object
121
+ keyed by the hash keys. All strings will either be returned as string or as
122
+ buffer depending on your setting. Please be aware that sending null, undefined
123
+ and Boolean values will result in the value coerced to a string!
124
+
125
+ # Redis Commands
126
+
127
+ This library is a 1 to 1 mapping to [Redis commands](https://redis.io/commands).
128
+ It is not a cache library so please refer to Redis commands page for full usage
129
+ details.
130
+
131
+ Example setting key to auto expire using [SET command](https://redis.io/commands/set)
132
+
133
+ ```js
134
+ // this key will expire after 10 seconds
135
+ client.set('key', 'value!', 'EX', 10);
136
+ ```
116
137
 
117
138
  # API
118
139
 
@@ -122,8 +143,9 @@ Please be aware that sending null, undefined and Boolean values will result in t
122
143
 
123
144
  ### "ready"
124
145
 
125
- `client` will emit `ready` once a connection is established. Commands issued before the `ready` event are queued,
126
- then replayed just before this event is emitted.
146
+ `client` will emit `ready` once a connection is established. Commands issued
147
+ before the `ready` event are queued, then replayed just before this event is
148
+ emitted.
127
149
 
128
150
  ### "connect"
129
151
 
@@ -131,13 +153,16 @@ then replayed just before this event is emitted.
131
153
 
132
154
  ### "reconnecting"
133
155
 
134
- `client` will emit `reconnecting` when trying to reconnect to the Redis server after losing the connection. Listeners
135
- are passed an object containing `delay` (in ms) and `attempt` (the attempt #) attributes.
156
+ `client` will emit `reconnecting` when trying to reconnect to the Redis server
157
+ after losing the connection. Listeners are passed an object containing `delay`
158
+ (in ms) and `attempt` (the attempt #) attributes.
136
159
 
137
160
  ### "error"
138
161
 
139
- `client` will emit `error` when encountering an error connecting to the Redis server or when any other in node_redis occurs.
140
- If you use a command without callback and encounter a ReplyError it is going to be emitted to the error listener.
162
+ `client` will emit `error` when encountering an error connecting to the Redis
163
+ server or when any other in node_redis occurs. If you use a command without
164
+ callback and encounter a ReplyError it is going to be emitted to the error
165
+ listener.
141
166
 
142
167
  So please attach the error listener to node_redis.
143
168
 
@@ -147,33 +172,41 @@ So please attach the error listener to node_redis.
147
172
 
148
173
  ### "drain" (deprecated)
149
174
 
150
- `client` will emit `drain` when the TCP connection to the Redis server has been buffering, but is now
151
- writable. This event can be used to stream commands in to Redis and adapt to backpressure.
175
+ `client` will emit `drain` when the TCP connection to the Redis server has been
176
+ buffering, but is now writable. This event can be used to stream commands in to
177
+ Redis and adapt to backpressure.
152
178
 
153
- If the stream is buffering `client.should_buffer` is set to true. Otherwise the variable is always set to false.
154
- That way you can decide when to reduce your send rate and resume sending commands when you get `drain`.
179
+ If the stream is buffering `client.should_buffer` is set to true. Otherwise the
180
+ variable is always set to false. That way you can decide when to reduce your
181
+ send rate and resume sending commands when you get `drain`.
155
182
 
156
- You can also check the return value of each command as it will also return the backpressure indicator (deprecated).
157
- If false is returned the stream had to buffer.
183
+ You can also check the return value of each command as it will also return the
184
+ backpressure indicator (deprecated). If false is returned the stream had to
185
+ buffer.
158
186
 
159
187
  ### "warning"
160
188
 
161
- `client` will emit `warning` when password was set but none is needed and if a deprecated option / function / similar is used.
189
+ `client` will emit `warning` when password was set but none is needed and if a
190
+ deprecated option / function / similar is used.
162
191
 
163
192
  ### "idle" (deprecated)
164
193
 
165
- `client` will emit `idle` when there are no outstanding commands that are awaiting a response.
194
+ `client` will emit `idle` when there are no outstanding commands that are
195
+ awaiting a response.
166
196
 
167
197
  ## redis.createClient()
168
- If you have `redis-server` running on the same machine as node, then the defaults for
169
- port and host are probably fine and you don't need to supply any arguments. `createClient()` returns a `RedisClient` object. Otherwise, `createClient()` accepts these arguments:
198
+ If you have `redis-server` running on the same machine as node, then the
199
+ defaults for port and host are probably fine and you don't need to supply any
200
+ arguments. `createClient()` returns a `RedisClient` object. Otherwise,
201
+ `createClient()` accepts these arguments:
170
202
 
171
203
  * `redis.createClient([options])`
172
204
  * `redis.createClient(unix_socket[, options])`
173
205
  * `redis.createClient(redis_url[, options])`
174
206
  * `redis.createClient(port[, host][, options])`
175
207
 
176
- __Tip:__ If the Redis server runs on the same machine as the client consider using unix sockets if possible to increase throughput.
208
+ __Tip:__ If the Redis server runs on the same machine as the client consider
209
+ using unix sockets if possible to increase throughput.
177
210
 
178
211
  #### `options` object properties
179
212
  | Property | Default | Description |
@@ -197,7 +230,7 @@ __Tip:__ If the Redis server runs on the same machine as the client consider usi
197
230
  | db | null | If set, client will run Redis `select` command on connect. |
198
231
  | family | IPv4 | You can force using IPv6 if you set the family to 'IPv6'. See Node.js [net](https://nodejs.org/api/net.html) or [dns](https://nodejs.org/api/dns.html) modules on how to use the family type. |
199
232
  | disable_resubscribing | false | If set to `true`, a client won't resubscribe after disconnecting. |
200
- | rename_commands | null | Passing an object with renamed commands to use instead of the original functions. See the [Redis security topics](http://redis.io/topics/security) for more info. |
233
+ | rename_commands | null | Passing an object with renamed commands to use instead of the original functions. For example, if you renamed the command KEYS to "DO-NOT-USE" then the rename_commands object would be: `{ KEYS : "DO-NOT-USE" }` . See the [Redis security topics](http://redis.io/topics/security) for more info. |
201
234
  | tls | null | An object containing options to pass to [tls.connect](http://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback) to set up a TLS connection to Redis (if, for example, it is set up to be accessible via a tunnel). |
202
235
  | prefix | null | A string used to prefix all used keys (e.g. `namespace:test`). Please be aware that the `keys` command will not be prefixed. The `keys` command has a "pattern" as argument and no key and it would be impossible to determine the existing keys in Redis if this would be prefixed. |
203
236
  | retry_strategy | function | A function that receives an options object as parameter including the retry `attempt`, the `total_retry_time` indicating how much time passed since the last time connected, the `error` why the connection was lost and the number of `times_connected` in total. If you return a number from this function, the retry will happen exactly after that time in milliseconds. If you return a non-number, no further retry will happen and all offline commands are flushed with errors. Return an error to return that specific error to all offline commands. Example below. |
@@ -221,18 +254,21 @@ client.quit();
221
254
  ```
222
255
 
223
256
  retry_strategy example
257
+
224
258
  ```js
225
259
  var client = redis.createClient({
226
260
  retry_strategy: function (options) {
227
261
  if (options.error && options.error.code === 'ECONNREFUSED') {
228
- // End reconnecting on a specific error and flush all commands with a individual error
262
+ // End reconnecting on a specific error and flush all commands with
263
+ // a individual error
229
264
  return new Error('The server refused the connection');
230
265
  }
231
266
  if (options.total_retry_time > 1000 * 60 * 60) {
232
- // End reconnecting after a specific timeout and flush all commands with a individual error
267
+ // End reconnecting after a specific timeout and flush all commands
268
+ // with a individual error
233
269
  return new Error('Retry time exhausted');
234
270
  }
235
- if (options.times_connected > 10) {
271
+ if (options.attempt > 10) {
236
272
  // End reconnecting with built in error
237
273
  return undefined;
238
274
  }
@@ -244,11 +280,12 @@ var client = redis.createClient({
244
280
 
245
281
  ## client.auth(password[, callback])
246
282
 
247
- When connecting to a Redis server that requires authentication, the `AUTH` command must be sent as the
248
- first command after connecting. This can be tricky to coordinate with reconnections, the ready check,
249
- etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection,
250
- including reconnections. `callback` is invoked only once, after the response to the very first
251
- `AUTH` command sent.
283
+ When connecting to a Redis server that requires authentication, the `AUTH`
284
+ command must be sent as the first command after connecting. This can be tricky
285
+ to coordinate with reconnections, the ready check, etc. To make this easier,
286
+ `client.auth()` stashes `password` and will send it after each connection,
287
+ including reconnections. `callback` is invoked only once, after the response to
288
+ the very first `AUTH` command sent.
252
289
  NOTE: Your call to `client.auth()` should not be inside the ready handler. If
253
290
  you are doing this wrong, `client` will emit an error that looks
254
291
  something like this `Error: Ready check failed: ERR operation not permitted`.
@@ -257,25 +294,34 @@ something like this `Error: Ready check failed: ERR operation not permitted`.
257
294
 
258
295
  ### stream
259
296
 
260
- The client exposed the used [stream](https://nodejs.org/api/stream.html) in `client.stream` and if the stream or client had to [buffer](https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback) the command in `client.should_buffer`.
261
- In combination this can be used to implement backpressure by checking the buffer state before sending a command and listening to the stream [drain](https://nodejs.org/api/stream.html#stream_event_drain) event.
297
+ The client exposed the used [stream](https://nodejs.org/api/stream.html) in
298
+ `client.stream` and if the stream or client had to
299
+ [buffer](https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback)
300
+ the command in `client.should_buffer`. In combination this can be used to
301
+ implement backpressure by checking the buffer state before sending a command and
302
+ listening to the stream
303
+ [drain](https://nodejs.org/api/stream.html#stream_event_drain) event.
262
304
 
263
305
  ## client.quit()
264
306
 
265
- This sends the quit command to the redis server and ends cleanly right after all running commands were properly handled.
266
- If this is called while reconnecting (and therefor no connection to the redis server exists) it is going to end the connection right away instead of
267
- resulting in further reconnections! All offline commands are going to be flushed with an error in that case.
307
+ This sends the quit command to the redis server and ends cleanly right after all
308
+ running commands were properly handled. If this is called while reconnecting
309
+ (and therefore no connection to the redis server exists) it is going to end the
310
+ connection right away instead of resulting in further reconnections! All offline
311
+ commands are going to be flushed with an error in that case.
268
312
 
269
313
  ## client.end(flush)
270
314
 
271
- Forcibly close the connection to the Redis server. Note that this does not wait until all replies have been parsed.
272
- If you want to exit cleanly, call `client.quit()` as mentioned above.
315
+ Forcibly close the connection to the Redis server. Note that this does not wait
316
+ until all replies have been parsed. If you want to exit cleanly, call
317
+ `client.quit()` as mentioned above.
273
318
 
274
- You should set flush to true, if you are not absolutely sure you do not care about any other commands.
275
- If you set flush to false all still running commands will silently fail.
319
+ You should set flush to true, if you are not absolutely sure you do not care
320
+ about any other commands. If you set flush to false all still running commands
321
+ will silently fail.
276
322
 
277
- This example closes the connection to the Redis server before the replies have been read. You probably don't
278
- want to do this:
323
+ This example closes the connection to the Redis server before the replies have
324
+ been read. You probably don't want to do this:
279
325
 
280
326
  ```js
281
327
  var redis = require("redis"),
@@ -296,10 +342,19 @@ client.get("foo_rand000000000000", function (err, reply) {
296
342
 
297
343
  ## Error handling (>= v.2.6)
298
344
 
299
- All redis errors are returned as `ReplyError`.
300
- All unresolved commands that get rejected due to what ever reason return a `AbortError`.
301
- As subclass of the `AbortError` a `AggregateError` exists. This is emitted in case multiple unresolved commands without callback got rejected in debug_mode.
302
- They are all aggregated and a single error is emitted in that case.
345
+ Currently the following error subclasses exist:
346
+
347
+ * `RedisError`: _All errors_ returned by the client
348
+ * `ReplyError` subclass of `RedisError`: All errors returned by __Redis__ itself
349
+ * `AbortError` subclass of `RedisError`: All commands that could not finish due
350
+ to what ever reason
351
+ * `ParserError` subclass of `RedisError`: Returned in case of a parser error
352
+ (this should not happen)
353
+ * `AggregateError` subclass of `AbortError`: Emitted in case multiple unresolved
354
+ commands without callback got rejected in debug_mode instead of lots of
355
+ `AbortError`s.
356
+
357
+ All error classes are exported by the module.
303
358
 
304
359
  Example:
305
360
  ```js
@@ -311,10 +366,11 @@ client.on('error', function (err) {
311
366
  assert(err instanceof Error);
312
367
  assert(err instanceof redis.AbortError);
313
368
  assert(err instanceof redis.AggregateError);
314
- assert.strictEqual(err.errors.length, 2); // The set and get got aggregated in here
369
+ // The set and get get aggregated in here
370
+ assert.strictEqual(err.errors.length, 2);
315
371
  assert.strictEqual(err.code, 'NR_CLOSED');
316
372
  });
317
- client.set('foo', 123, 'bar', function (err, res) { // To many arguments
373
+ client.set('foo', 123, 'bar', function (err, res) { // Too many arguments
318
374
  assert(err instanceof redis.ReplyError); // => true
319
375
  assert.strictEqual(err.command, 'SET');
320
376
  assert.deepStrictEqual(err.args, ['foo', 123, 'bar']);
@@ -323,7 +379,8 @@ client.set('foo', 123, 'bar', function (err, res) { // To many arguments
323
379
  client.set('foo', 'bar');
324
380
  client.get('foo');
325
381
  process.nextTick(function () {
326
- client.end(true); // Force closing the connection while the command did not yet return
382
+ // Force closing the connection while the command did not yet return
383
+ client.end(true);
327
384
  redis.debug_mode = false;
328
385
  });
329
386
  });
@@ -332,25 +389,33 @@ client.set('foo', 123, 'bar', function (err, res) { // To many arguments
332
389
 
333
390
  Every `ReplyError` contains the `command` name in all-caps and the arguments (`args`).
334
391
 
335
- If node_redis emits a library error because of another error, the triggering error is added to the returned error as `origin` attribute.
392
+ If node_redis emits a library error because of another error, the triggering
393
+ error is added to the returned error as `origin` attribute.
336
394
 
337
395
  ___Error codes___
338
396
 
339
- node_redis returns a `NR_CLOSED` error code if the clients connection dropped. If a command unresolved command got rejected a `UNERCTAIN_STATE` code is returned.
340
- A `CONNECTION_BROKEN` error code is used in case node_redis gives up to reconnect.
397
+ node_redis returns a `NR_CLOSED` error code if the clients connection dropped.
398
+ If a command unresolved command got rejected a `UNCERTAIN_STATE` code is
399
+ returned. A `CONNECTION_BROKEN` error code is used in case node_redis gives up
400
+ to reconnect.
341
401
 
342
402
  ## client.unref()
343
403
 
344
- Call `unref()` on the underlying socket connection to the Redis server, allowing the program to exit once no more commands are pending.
404
+ Call `unref()` on the underlying socket connection to the Redis server, allowing
405
+ the program to exit once no more commands are pending.
345
406
 
346
- This is an **experimental** feature, and only supports a subset of the Redis protocol. Any commands where client state is saved on the Redis server, e.g. `*SUBSCRIBE` or the blocking `BL*` commands will *NOT* work with `.unref()`.
407
+ This is an **experimental** feature, and only supports a subset of the Redis
408
+ protocol. Any commands where client state is saved on the Redis server, e.g.
409
+ `*SUBSCRIBE` or the blocking `BL*` commands will *NOT* work with `.unref()`.
347
410
 
348
411
  ```js
349
412
  var redis = require("redis")
350
413
  var client = redis.createClient()
351
414
 
352
415
  /*
353
- Calling unref() will allow this program to exit immediately after the get command finishes. Otherwise the client would hang as long as the client-server connection is alive.
416
+ Calling unref() will allow this program to exit immediately after the get
417
+ command finishes. Otherwise the client would hang as long as the
418
+ client-server connection is alive.
354
419
  */
355
420
  client.unref()
356
421
  client.get("foo", function (err, value){
@@ -361,13 +426,15 @@ client.get("foo", function (err, value){
361
426
 
362
427
  ## Friendlier hash commands
363
428
 
364
- Most Redis commands take a single String or an Array of Strings as arguments, and replies are sent back as a single String or an Array of Strings.
365
- When dealing with hash values, there are a couple of useful exceptions to this.
429
+ Most Redis commands take a single String or an Array of Strings as arguments,
430
+ and replies are sent back as a single String or an Array of Strings. When
431
+ dealing with hash values, there are a couple of useful exceptions to this.
366
432
 
367
433
  ### client.hgetall(hash, callback)
368
434
 
369
- The reply from an HGETALL command will be converted into a JavaScript Object by `node_redis`. That way you can interact
370
- with the responses using JavaScript syntax.
435
+ The reply from an HGETALL command will be converted into a JavaScript Object by
436
+ `node_redis`. That way you can interact with the responses using JavaScript
437
+ syntax.
371
438
 
372
439
  Example:
373
440
 
@@ -395,7 +462,8 @@ client.HMSET(key2, {
395
462
  });
396
463
  ```
397
464
 
398
- The properties and values of this Object will be set as keys and values in the Redis hash.
465
+ The properties and values of this Object will be set as keys and values in the
466
+ Redis hash.
399
467
 
400
468
  ### client.hmset(hash, key1, val1, ... keyn, valn, [callback])
401
469
 
@@ -435,11 +503,13 @@ sub.on("message", function (channel, message) {
435
503
  sub.subscribe("a nice channel");
436
504
  ```
437
505
 
438
- When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into a "subscriber" mode.
439
- At that point, only commands that modify the subscription set are valid and quit (and depending on the redis version ping as well). When the subscription
440
- set is empty, the connection is put back into regular mode.
506
+ When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into
507
+ a "subscriber" mode. At that point, only commands that modify the subscription
508
+ set are valid and quit (and depending on the redis version ping as well). When
509
+ the subscription set is empty, the connection is put back into regular mode.
441
510
 
442
- If you need to send regular commands to Redis while in subscriber mode, just open another connection with a new client (hint: use `client.duplicate()`).
511
+ If you need to send regular commands to Redis while in subscriber mode, just
512
+ open another connection with a new client (hint: use `client.duplicate()`).
443
513
 
444
514
  ## Subscriber Events
445
515
 
@@ -452,47 +522,57 @@ Listeners are passed the channel name as `channel` and the message as `message`.
452
522
 
453
523
  ### "pmessage" (pattern, channel, message)
454
524
 
455
- Client will emit `pmessage` for every message received that matches an active subscription pattern.
456
- Listeners are passed the original pattern used with `PSUBSCRIBE` as `pattern`, the sending channel
457
- name as `channel`, and the message as `message`.
525
+ Client will emit `pmessage` for every message received that matches an active
526
+ subscription pattern. Listeners are passed the original pattern used with
527
+ `PSUBSCRIBE` as `pattern`, the sending channel name as `channel`, and the
528
+ message as `message`.
458
529
 
459
530
  ### "message_buffer" (channel, message)
460
531
 
461
- This is the same as the `message` event with the exception, that it is always going to emit a buffer.
462
- If you listen to the `message` event at the same time as the `message_buffer`, it is always going to emit a string.
532
+ This is the same as the `message` event with the exception, that it is always
533
+ going to emit a buffer. If you listen to the `message` event at the same time as
534
+ the `message_buffer`, it is always going to emit a string.
463
535
 
464
536
  ### "pmessage_buffer" (pattern, channel, message)
465
537
 
466
- This is the same as the `pmessage` event with the exception, that it is always going to emit a buffer.
467
- If you listen to the `pmessage` event at the same time as the `pmessage_buffer`, it is always going to emit a string.
538
+ This is the same as the `pmessage` event with the exception, that it is always
539
+ going to emit a buffer. If you listen to the `pmessage` event at the same time
540
+ as the `pmessage_buffer`, it is always going to emit a string.
468
541
 
469
542
  ### "subscribe" (channel, count)
470
543
 
471
- Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are passed the
472
- channel name as `channel` and the new count of subscriptions for this client as `count`.
544
+ Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are
545
+ passed the channel name as `channel` and the new count of subscriptions for this
546
+ client as `count`.
473
547
 
474
548
  ### "psubscribe" (pattern, count)
475
549
 
476
- Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners are passed the
477
- original pattern as `pattern`, and the new count of subscriptions for this client as `count`.
550
+ Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners
551
+ are passed the original pattern as `pattern`, and the new count of subscriptions
552
+ for this client as `count`.
478
553
 
479
554
  ### "unsubscribe" (channel, count)
480
555
 
481
- Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners are passed the
482
- channel name as `channel` and the new count of subscriptions for this client as `count`. When
483
- `count` is 0, this client has left subscriber mode and no more subscriber events will be emitted.
556
+ Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners
557
+ are passed the channel name as `channel` and the new count of subscriptions for
558
+ this client as `count`. When `count` is 0, this client has left subscriber mode
559
+ and no more subscriber events will be emitted.
484
560
 
485
561
  ### "punsubscribe" (pattern, count)
486
562
 
487
- Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command. Listeners are passed the
488
- channel name as `channel` and the new count of subscriptions for this client as `count`. When
489
- `count` is 0, this client has left subscriber mode and no more subscriber events will be emitted.
563
+ Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command.
564
+ Listeners are passed the channel name as `channel` and the new count of
565
+ subscriptions for this client as `count`. When `count` is 0, this client has
566
+ left subscriber mode and no more subscriber events will be emitted.
490
567
 
491
568
  ## client.multi([commands])
492
569
 
493
- `MULTI` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by
494
- Redis. The interface in `node_redis` is to return an individual `Multi` object by calling `client.multi()`.
495
- If any command fails to queue, all commands are rolled back and none is going to be executed (For further information look at [transactions](http://redis.io/topics/transactions)).
570
+ `MULTI` commands are queued up until an `EXEC` is issued, and then all commands
571
+ are run atomically by Redis. The interface in `node_redis` is to return an
572
+ individual `Multi` object by calling `client.multi()`. If any command fails to
573
+ queue, all commands are rolled back and none is going to be executed (For
574
+ further information look at
575
+ [transactions](http://redis.io/topics/transactions)).
496
576
 
497
577
  ```js
498
578
  var redis = require("./index"),
@@ -526,15 +606,20 @@ client.multi()
526
606
 
527
607
  ### Multi.exec([callback])
528
608
 
529
- `client.multi()` is a constructor that returns a `Multi` object. `Multi` objects share all of the
530
- same command methods as `client` objects do. Commands are queued up inside the `Multi` object
531
- until `Multi.exec()` is invoked.
609
+ `client.multi()` is a constructor that returns a `Multi` object. `Multi` objects
610
+ share all of the same command methods as `client` objects do. Commands are
611
+ queued up inside the `Multi` object until `Multi.exec()` is invoked.
532
612
 
533
- If your code contains an syntax error an EXECABORT error is going to be thrown and all commands are going to be aborted. That error contains a `.errors` property that contains the concret errors.
534
- If all commands were queued successfully and an error is thrown by redis while processing the commands that error is going to be returned in the result array! No other command is going to be aborted though than the onces failing.
613
+ If your code contains an syntax error an EXECABORT error is going to be thrown
614
+ and all commands are going to be aborted. That error contains a `.errors`
615
+ property that contains the concrete errors.
616
+ If all commands were queued successfully and an error is thrown by redis while
617
+ processing the commands that error is going to be returned in the result array!
618
+ No other command is going to be aborted though than the onces failing.
535
619
 
536
- You can either chain together `MULTI` commands as in the above example, or you can queue individual
537
- commands while still sending regular client command as in this example:
620
+ You can either chain together `MULTI` commands as in the above example, or you
621
+ can queue individual commands while still sending regular client command as in
622
+ this example:
538
623
 
539
624
  ```js
540
625
  var redis = require("redis"),
@@ -554,8 +639,8 @@ multi.exec(function (err, replies) {
554
639
  });
555
640
  ```
556
641
 
557
- In addition to adding commands to the `MULTI` queue individually, you can also pass an array
558
- of commands and arguments to the constructor:
642
+ In addition to adding commands to the `MULTI` queue individually, you can also
643
+ pass an array of commands and arguments to the constructor:
559
644
 
560
645
  ```js
561
646
  var redis = require("redis"),
@@ -572,26 +657,36 @@ client.multi([
572
657
 
573
658
  ### Multi.exec_atomic([callback])
574
659
 
575
- Identical to Multi.exec but with the difference that executing a single command will not use transactions.
660
+ Identical to Multi.exec but with the difference that executing a single command
661
+ will not use transactions.
576
662
 
577
663
  ## client.batch([commands])
578
664
 
579
- Identical to .multi without transactions. This is recommended if you want to execute many commands at once but don't have to rely on transactions.
665
+ Identical to .multi without transactions. This is recommended if you want to
666
+ execute many commands at once but don't have to rely on transactions.
580
667
 
581
- `BATCH` commands are queued up until an `EXEC` is issued, and then all commands are run atomically by
582
- Redis. The interface in `node_redis` is to return an individual `Batch` object by calling `client.batch()`.
583
- The only difference between .batch and .multi is that no transaction is going to be used.
584
- Be aware that the errors are - just like in multi statements - in the result. Otherwise both, errors and results could be returned at the same time.
668
+ `BATCH` commands are queued up until an `EXEC` is issued, and then all commands
669
+ are run atomically by Redis. The interface in `node_redis` is to return an
670
+ individual `Batch` object by calling `client.batch()`. The only difference
671
+ between .batch and .multi is that no transaction is going to be used.
672
+ Be aware that the errors are - just like in multi statements - in the result.
673
+ Otherwise both, errors and results could be returned at the same time.
585
674
 
586
- If you fire many commands at once this is going to boost the execution speed significantly compared to fireing the same commands in a loop without waiting for the result! See the benchmarks for further comparison. Please remember that all commands are kept in memory until they are fired.
675
+ If you fire many commands at once this is going to boost the execution speed
676
+ significantly compared to firing the same commands in a loop without waiting for
677
+ the result! See the benchmarks for further comparison. Please remember that all
678
+ commands are kept in memory until they are fired.
587
679
 
588
680
  ## Monitor mode
589
681
 
590
- Redis supports the `MONITOR` command, which lets you see all commands received by the Redis server
591
- across all client connections, including from other client libraries and other computers.
682
+ Redis supports the `MONITOR` command, which lets you see all commands received
683
+ by the Redis server across all client connections, including from other client
684
+ libraries and other computers.
592
685
 
593
- A `monitor` event is going to be emitted for every command fired from any client connected to the server including the monitoring client itself.
594
- The callback for the `monitor` event takes a timestamp from the Redis server, an array of command arguments and the raw monitoring string.
686
+ A `monitor` event is going to be emitted for every command fired from any client
687
+ connected to the server including the monitoring client itself. The callback for
688
+ the `monitor` event takes a timestamp from the Redis server, an array of command
689
+ arguments and the raw monitoring string.
595
690
 
596
691
  Example:
597
692
 
@@ -613,10 +708,11 @@ Some other things you might like to know about.
613
708
 
614
709
  ## client.server_info
615
710
 
616
- After the ready probe completes, the results from the INFO command are saved in the `client.server_info`
617
- object.
711
+ After the ready probe completes, the results from the INFO command are saved in
712
+ the `client.server_info` object.
618
713
 
619
- The `versions` key contains an array of the elements of the version string for easy comparison.
714
+ The `versions` key contains an array of the elements of the version string for
715
+ easy comparison.
620
716
 
621
717
  > client.server_info.redis_version
622
718
  '2.3.0'
@@ -655,12 +751,15 @@ the second word as first parameter:
655
751
 
656
752
  ## client.duplicate([options][, callback])
657
753
 
658
- Duplicate all current options and return a new redisClient instance. All options passed to the duplicate function are going to replace the original option.
659
- If you pass a callback, duplicate is going to wait until the client is ready and returns it in the callback. If an error occurs in the meanwhile, that is going to return an error instead in the callback.
754
+ Duplicate all current options and return a new redisClient instance. All options
755
+ passed to the duplicate function are going to replace the original option. If
756
+ you pass a callback, duplicate is going to wait until the client is ready and
757
+ returns it in the callback. If an error occurs in the meanwhile, that is going
758
+ to return an error instead in the callback.
660
759
 
661
- One example of when to use duplicate() would be to accomodate the connection-
760
+ One example of when to use duplicate() would be to accommodate the connection-
662
761
  blocking redis commands BRPOP, BLPOP, and BRPOPLPUSH. If these commands
663
- are used on the same redisClient instance as non-blocking commands, the
762
+ are used on the same redisClient instance as non-blocking commands, the
664
763
  non-blocking ones may be queued up until after the blocking ones finish.
665
764
 
666
765
  var Redis=require('redis');
@@ -681,17 +780,25 @@ non-blocking ones may be queued up until after the blocking ones finish.
681
780
  };
682
781
  get();
683
782
  brpop();
684
-
685
- Another reason to use duplicate() is when multiple DBs on the same server are
783
+
784
+ Another reason to use duplicate() is when multiple DBs on the same server are
686
785
  accessed via the redis SELECT command. Each DB could use its own connection.
687
-
786
+
688
787
  ## client.send_command(command_name[, [args][, callback]])
689
788
 
690
- All Redis commands have been added to the `client` object. However, if new commands are introduced before this library is updated,
691
- you can use `send_command()` to send arbitrary commands to Redis.
692
- The command_name has to be lower case.
789
+ All Redis commands have been added to the `client` object. However, if new
790
+ commands are introduced before this library is updated or if you want to add
791
+ individual commands you can use `send_command()` to send arbitrary commands to
792
+ Redis.
693
793
 
694
- All commands are sent as multi-bulk commands. `args` can either be an Array of arguments, or omitted / set to undefined.
794
+ All commands are sent as multi-bulk commands. `args` can either be an Array of
795
+ arguments, or omitted / set to undefined.
796
+
797
+ ## client.add_command(command_name)
798
+
799
+ Calling add_command will add a new command to the prototype. The exact command
800
+ name will be used when calling using this new command. Using arbitrary arguments
801
+ is possible as with any other command.
695
802
 
696
803
  ## client.connected
697
804
 
@@ -699,19 +806,23 @@ Boolean tracking the state of the connection to the Redis server.
699
806
 
700
807
  ## client.command_queue_length
701
808
 
702
- The number of commands that have been sent to the Redis server but not yet replied to. You can use this to
703
- enforce some kind of maximum queue depth for commands while connected.
809
+ The number of commands that have been sent to the Redis server but not yet
810
+ replied to. You can use this to enforce some kind of maximum queue depth for
811
+ commands while connected.
704
812
 
705
813
  ## client.offline_queue_length
706
814
 
707
- The number of commands that have been queued up for a future connection. You can use this to enforce
708
- some kind of maximum queue depth for pre-connection commands.
815
+ The number of commands that have been queued up for a future connection. You can
816
+ use this to enforce some kind of maximum queue depth for pre-connection
817
+ commands.
709
818
 
710
819
  ### Commands with Optional and Keyword arguments
711
820
 
712
- This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation.
821
+ This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset
822
+ count]` in the [redis.io/commands](http://redis.io/commands) documentation.
713
823
 
714
824
  Example:
825
+
715
826
  ```js
716
827
  var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ];
717
828
  client.zadd(args, function (err, response) {
@@ -784,10 +895,13 @@ clients: 1, NodeJS: 6.2.0, Redis: 3.2.0, parser: javascript, connected by: tcp
784
895
 
785
896
  To get debug output run your `node_redis` application with `NODE_DEBUG=redis`.
786
897
 
787
- This is also going to result in good stack traces opposed to useless ones otherwise for any async operation.
788
- If you only want to have good stack traces but not the debug output run your application in development mode instead (`NODE_ENV=development`).
898
+ This is also going to result in good stack traces opposed to useless ones
899
+ otherwise for any async operation.
900
+ If you only want to have good stack traces but not the debug output run your
901
+ application in development mode instead (`NODE_ENV=development`).
789
902
 
790
- Good stack traces are only activated in development and debug mode as this results in a significant performance penalty.
903
+ Good stack traces are only activated in development and debug mode as this
904
+ results in a significant performance penalty.
791
905
 
792
906
  ___Comparison___:
793
907
  Useless stack trace:
@@ -823,7 +937,8 @@ The original author of node_redis is [Matthew Ranney](https://github.com/mranney
823
937
 
824
938
  The current lead maintainer is [Ruben Bridgewater](https://github.com/BridgeAR)
825
939
 
826
- Many [others](https://github.com/NodeRedis/node_redis/graphs/contributors) contributed to `node_redis` too. Thanks to all of them!
940
+ Many [others](https://github.com/NodeRedis/node_redis/graphs/contributors)
941
+ contributed to `node_redis` too. Thanks to all of them!
827
942
 
828
943
  ## License
829
944
 
@@ -831,10 +946,20 @@ Many [others](https://github.com/NodeRedis/node_redis/graphs/contributors) contr
831
946
 
832
947
  ### Consolidation: It's time for celebration
833
948
 
834
- Right now there are two great redis clients around and both have some advantages above each other. We speak about ioredis and node_redis. So after talking to each other about how we could improve in working together we (that is @luin and @BridgeAR) decided to work towards a single library on the long run. But step by step.
949
+ Right now there are two great redis clients around and both have some advantages
950
+ above each other. We speak about ioredis and node_redis. So after talking to
951
+ each other about how we could improve in working together we (that is @luin and
952
+ @BridgeAR) decided to work towards a single library on the long run. But step by
953
+ step.
835
954
 
836
- First of all, we want to split small parts of our libraries into others so that we're both able to use the same code. Those libraries are going to be maintained under the NodeRedis organization. This is going to reduce the maintance overhead, allows others to use the very same code, if they need it and it's way easyer for others to contribute to both libraries.
955
+ First of all, we want to split small parts of our libraries into others so that
956
+ we're both able to use the same code. Those libraries are going to be maintained
957
+ under the NodeRedis organization. This is going to reduce the maintenance
958
+ overhead, allows others to use the very same code, if they need it and it's way
959
+ easyer for others to contribute to both libraries.
837
960
 
838
- We're very happy about this step towards working together as we both want to give you the best redis experience possible.
961
+ We're very happy about this step towards working together as we both want to
962
+ give you the best redis experience possible.
839
963
 
840
- If you want to join our cause by help maintaining something, please don't hesitate to contact either one of us.
964
+ If you want to join our cause by help maintaining something, please don't
965
+ hesitate to contact either one of us.
package/changelog.md CHANGED
@@ -1,30 +1,66 @@
1
- Changelog
2
- =========
1
+ # Changelog
2
+
3
+ ## v.2.8.0 - 31 Jul, 2017
4
+
5
+ Features
6
+
7
+ - Accept UPPER_CASE commands in send_command
8
+ - Add arbitrary commands to the prototype by using `Redis.addCommand(name)`
9
+
10
+ Bugfixes
11
+
12
+ - Fixed not always copying subscribe unsubscribe arguments
13
+ - Fixed emitting internal errors while reconnecting with auth
14
+ - Fixed crashing with invalid url option
15
+
16
+ ## v.2.7.1 - 14 Mar, 2017
17
+
18
+ Bugfixes
19
+
20
+ - Fixed monitor mode not working in combination with IPv6 (2.6.0 regression)
21
+
22
+ ## v.2.7.0 - 11 Mar, 2017
23
+
24
+ Features
25
+
26
+ - All returned errors are from now a subclass of `RedisError`.
27
+
28
+ Bugfixes
29
+
30
+ - Fixed rename_commands not accepting `null` as value
31
+ - Fixed `AbortError`s and `AggregateError`s not showing the error message in the stack trace
32
+
33
+ ## v.2.6.5 - 15 Jan, 2017
34
+
35
+ Bugfixes
36
+
37
+ - Fixed parser not being reset in case the redis connection closed ASAP for overcoming of output buffer limits
38
+ - Fixed parser reset if (p)message_buffer listener is attached
3
39
 
4
40
  ## v.2.6.4 - 12 Jan, 2017
5
41
 
6
42
  Bugfixes
7
43
 
8
- - Fixed monitor mode not working in combination with IPv6, sockets or lua scripts (2.6.0 regression)
44
+ - Fixed monitor mode not working in combination with IPv6, sockets or lua scripts (2.6.0 regression)
9
45
 
10
46
  ## v.2.6.3 - 31 Oct, 2016
11
47
 
12
48
  Bugfixes
13
49
 
14
- - Do not change the tls setting to camel_case
15
- - Fix domain handling in combination with the offline queue (2.5.3 regression)
50
+ - Do not change the tls setting to camel_case
51
+ - Fix domain handling in combination with the offline queue (2.5.3 regression)
16
52
 
17
53
  ## v.2.6.2 - 16 Jun, 2016
18
54
 
19
55
  Bugfixes
20
56
 
21
- - Fixed individual callbacks of a transaction not being called (2.6.0 regression)
57
+ - Fixed individual callbacks of a transaction not being called (2.6.0 regression)
22
58
 
23
59
  ## v.2.6.1 - 02 Jun, 2016
24
60
 
25
61
  Bugfixes
26
62
 
27
- - Fixed invalid function name being exported
63
+ - Fixed invalid function name being exported
28
64
 
29
65
  ## v.2.6.0 - 01 Jun, 2016
30
66
 
@@ -106,7 +142,7 @@ Features
106
142
  - Monitor and pub sub mode now work together with the offline queue
107
143
  - All commands that were send after a connection loss are now going to be send after reconnecting
108
144
  - Activating monitor mode does now work together with arbitrary commands including pub sub mode
109
- - Pub sub mode is completly rewritten and all known issues fixed
145
+ - Pub sub mode is completely rewritten and all known issues fixed
110
146
  - Added `string_numbers` option to get back strings instead of numbers
111
147
  - Quit command is from now on always going to end the connection properly
112
148
 
@@ -149,7 +185,7 @@ Same changelog as the pre-release
149
185
 
150
186
  ## v.2.5.0-1 - 07 Mar, 2016
151
187
 
152
- This is a big release with some substaintual underlining changes. Therefor this is released as a pre-release and I encourage anyone who's able to, to test this out.
188
+ This is a big release with some substantial underlining changes. Therefor this is released as a pre-release and I encourage anyone who's able to, to test this out.
153
189
 
154
190
  It took way to long to release this one and the next release cycles will be shorter again.
155
191
 
@@ -169,7 +205,7 @@ Features
169
205
  - Added a `warning` emitter that receives node_redis warnings like auth not required and deprecation messages
170
206
  - Added a `retry_strategy` option that replaces all reconnect options
171
207
  - The reconnecting event from now on also receives:
172
- - The error message why the reconnect happend (params.error)
208
+ - The error message why the reconnect happened (params.error)
173
209
  - The amount of times the client was connected (params.times_connected)
174
210
  - The total reconnecting time since the last time connected (params.total_retry_time)
175
211
  - Always respect the command execution order no matter if the reply could be returned sync or not (former exceptions: [#937](https://github.com/NodeRedis/node_redis/issues/937#issuecomment-167525939))
@@ -184,9 +220,9 @@ Bugfixes
184
220
  - Fixed do not run toString on an array argument and throw a "invalid data" error instead
185
221
  - This is not considered as breaking change, as this is likely a error in your code and if you want to have such a behavior you should handle this beforehand
186
222
  - The same applies to Map / Set and individual Object types
187
- - Fixed redis url not accepting the protocol being omitted or protocols other than the redis protocol for convienence
223
+ - Fixed redis url not accepting the protocol being omitted or protocols other than the redis protocol for convenience
188
224
  - Fixed parsing the db keyspace even if the first database does not begin with a zero
189
- - Fixed handling of errors occuring while receiving pub sub messages
225
+ - Fixed handling of errors occurring while receiving pub sub messages
190
226
  - Fixed huge string pipelines crashing NodeJS (Pipeline size above 256mb)
191
227
  - Fixed rename_commands and prefix option not working together
192
228
  - Fixed ready being emitted to early in case a slave is still syncing / master down
@@ -199,7 +235,7 @@ Deprecations
199
235
  - Using SET or SETEX with a undefined or null value will from now on also result in converting the value to "null" / "undefined" to have a consistent behavior. This is not considered as breaking change, as it returned an error earlier.
200
236
  - Using .end(flush) without the flush parameter is deprecated and the flush parameter should explicitly be used
201
237
  - From v.3.0.0 on using .end without flush will result in an error
202
- - Using .end without flush means that any command that did not yet return is going to silently fail. Therefor this is considered harmfull and you should explicitly silence such errors if you are sure you want this
238
+ - Using .end without flush means that any command that did not yet return is going to silently fail. Therefor this is considered harmful and you should explicitly silence such errors if you are sure you want this
203
239
  - Depending on the return value of a command to detect the backpressure is deprecated
204
240
  - From version 3.0.0 on node_redis might not return true / false as a return value anymore. Please rely on client.should_buffer instead
205
241
  - The `socket_nodelay` option is deprecated and will be removed in v.3.0.0
package/index.js CHANGED
@@ -120,7 +120,7 @@ function RedisClient (options, stream) {
120
120
  if ('max_attempts' in options) {
121
121
  self.warn(
122
122
  'max_attempts is deprecated and will be removed in v.3.0.0.\n' +
123
- 'To reduce the amount of options and the improve the reconnection handling please use the new `retry_strategy` option instead.\n' +
123
+ 'To reduce the number of options and to improve the reconnection handling please use the new `retry_strategy` option instead.\n' +
124
124
  'This replaces the max_attempts and retry_max_delay option.'
125
125
  );
126
126
  }
@@ -156,8 +156,6 @@ function RedisClient (options, stream) {
156
156
  this.buffers = options.return_buffers || options.detect_buffers;
157
157
  this.options = options;
158
158
  this.reply = 'ON'; // Returning replies is the default
159
- // Init parser
160
- this.reply_parser = create_parser(this);
161
159
  this.create_stream();
162
160
  // The listeners will not be attached right away, so let's print the deprecation message while the listener is attached
163
161
  this.on('newListener', function (event) {
@@ -171,10 +169,16 @@ function RedisClient (options, stream) {
171
169
  'The drain event listener is deprecated and will be removed in v.3.0.0.\n' +
172
170
  'If you want to keep on listening to this event please listen to the stream drain event directly.'
173
171
  );
174
- } else if (event === 'message_buffer' || event === 'pmessage_buffer' || event === 'messageBuffer' || event === 'pmessageBuffer' && !this.buffers) {
172
+ } else if ((event === 'message_buffer' || event === 'pmessage_buffer' || event === 'messageBuffer' || event === 'pmessageBuffer') && !this.buffers && !this.message_buffers) {
173
+ if (this.reply_parser.name !== 'javascript') {
174
+ return this.warn(
175
+ 'You attached the "' + event + '" listener without the returnBuffers option set to true.\n' +
176
+ 'Please use the JavaScript parser or set the returnBuffers option to true to return buffers.'
177
+ );
178
+ }
179
+ this.reply_parser.optionReturnBuffers = true;
175
180
  this.message_buffers = true;
176
181
  this.handle_reply = handle_detect_buffers_reply;
177
- this.reply_parser = create_parser(this);
178
182
  }
179
183
  });
180
184
  }
@@ -224,6 +228,9 @@ function create_parser (self) {
224
228
  RedisClient.prototype.create_stream = function () {
225
229
  var self = this;
226
230
 
231
+ // Init parser
232
+ this.reply_parser = create_parser(this);
233
+
227
234
  if (this.options.stream) {
228
235
  // Only add the listeners once in case of a reconnect try (that won't work)
229
236
  if (this.stream) {
@@ -297,7 +304,12 @@ RedisClient.prototype.create_stream = function () {
297
304
  // Fire the command before redis is connected to be sure it's the first fired command
298
305
  if (this.auth_pass !== undefined) {
299
306
  this.ready = true;
300
- this.auth(this.auth_pass);
307
+ // Fail silently as we might not be able to connect
308
+ this.auth(this.auth_pass, function (err) {
309
+ if (err && err.code !== 'UNCERTAIN_STATE') {
310
+ self.emit('error', err);
311
+ }
312
+ });
301
313
  this.ready = false;
302
314
  }
303
315
  };
@@ -924,7 +936,7 @@ RedisClient.prototype.internal_send_command = function (command_obj) {
924
936
  args_copy[i] = this.options.prefix + args_copy[i];
925
937
  }
926
938
  }
927
- if (typeof this.options.rename_commands !== 'undefined' && this.options.rename_commands[command]) {
939
+ if (this.options.rename_commands && this.options.rename_commands[command]) {
928
940
  command = this.options.rename_commands[command];
929
941
  }
930
942
  // Always use 'Multi bulk commands', but if passed any Buffer args, then do multiple writes, one for each arg.
@@ -1080,10 +1092,14 @@ exports.RedisClient = RedisClient;
1080
1092
  exports.print = utils.print;
1081
1093
  exports.Multi = require('./lib/multi');
1082
1094
  exports.AbortError = errorClasses.AbortError;
1095
+ exports.RedisError = Parser.RedisError;
1096
+ exports.ParserError = Parser.ParserError;
1083
1097
  exports.ReplyError = Parser.ReplyError;
1084
1098
  exports.AggregateError = errorClasses.AggregateError;
1085
1099
 
1086
1100
  // Add all redis commands / node_redis api to the client
1087
1101
  require('./lib/individualCommands');
1088
1102
  require('./lib/extendedApi');
1089
- require('./lib/commands');
1103
+
1104
+ //enables adding new commands (for modules and new commands)
1105
+ exports.addCommand = exports.add_command = require('./lib/commands');
package/lib/commands.js CHANGED
@@ -17,11 +17,7 @@ var changeFunctionName = (function () {
17
17
  }
18
18
  }());
19
19
 
20
- // TODO: Rewrite this including the invidual commands into a Commands class
21
- // that provided a functionality to add new commands to the client
22
-
23
- commands.list.forEach(function (command) {
24
-
20
+ var addCommand = function (command) {
25
21
  // Some rare Redis commands use special characters in their command name
26
22
  // Convert those to a underscore to prevent using invalid function names
27
23
  var commandName = command.replace(/(?:^([0-9])|[^a-zA-Z0-9_$])/g, '_$1');
@@ -61,6 +57,10 @@ commands.list.forEach(function (command) {
61
57
  }
62
58
  return this.internal_send_command(new Command(command, arr, callback));
63
59
  };
60
+ // Alias special function names (e.g. NR.RUN becomes NR_RUN and nr_run)
61
+ if (commandName !== command) {
62
+ RedisClient.prototype[commandName.toUpperCase()] = RedisClient.prototype[commandName] = RedisClient.prototype[command];
63
+ }
64
64
  if (changeFunctionName) {
65
65
  Object.defineProperty(RedisClient.prototype[command], 'name', {
66
66
  value: commandName
@@ -104,10 +104,18 @@ commands.list.forEach(function (command) {
104
104
  this.queue.push(new Command(command, arr, callback));
105
105
  return this;
106
106
  };
107
+ // Alias special function names (e.g. NR.RUN becomes NR_RUN and nr_run)
108
+ if (commandName !== command) {
109
+ Multi.prototype[commandName.toUpperCase()] = Multi.prototype[commandName] = Multi.prototype[command];
110
+ }
107
111
  if (changeFunctionName) {
108
112
  Object.defineProperty(Multi.prototype[command], 'name', {
109
113
  value: commandName
110
114
  });
111
115
  }
112
116
  }
113
- });
117
+ };
118
+
119
+ commands.list.forEach(addCommand);
120
+
121
+ module.exports = addCommand;
@@ -23,7 +23,8 @@ module.exports = function createClient (port_arg, host_arg, options) {
23
23
  } else if (typeof port_arg === 'string' || port_arg && port_arg.url) {
24
24
 
25
25
  options = utils.clone(port_arg.url ? port_arg : host_arg || options);
26
- var parsed = URL.parse(port_arg.url || port_arg, true, true);
26
+ var url = port_arg.url || port_arg;
27
+ var parsed = URL.parse(url, true, true);
27
28
 
28
29
  // [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
29
30
  if (parsed.slashes) { // We require slashes
@@ -59,7 +60,7 @@ module.exports = function createClient (port_arg, host_arg, options) {
59
60
  } else if (parsed.hostname) {
60
61
  throw new RangeError('The redis url must begin with slashes "//" or contain slashes after the redis protocol');
61
62
  } else {
62
- options.path = port_arg;
63
+ options.path = url;
63
64
  }
64
65
 
65
66
  } else if (typeof port_arg === 'object' || port_arg === undefined) {
@@ -1,42 +1,55 @@
1
1
  'use strict';
2
2
 
3
3
  var util = require('util');
4
+ var assert = require('assert');
5
+ var RedisError = require('redis-parser').RedisError;
6
+ var ADD_STACKTRACE = false;
4
7
 
5
- function AbortError (obj) {
6
- Error.captureStackTrace(this, this.constructor);
8
+ function AbortError (obj, stack) {
9
+ assert(obj, 'The options argument is required');
10
+ assert.strictEqual(typeof obj, 'object', 'The options argument has to be of type object');
11
+
12
+ RedisError.call(this, obj.message, ADD_STACKTRACE);
7
13
  Object.defineProperty(this, 'message', {
8
14
  value: obj.message || '',
9
15
  configurable: true,
10
16
  writable: true
11
17
  });
18
+ if (stack || stack === undefined) {
19
+ Error.captureStackTrace(this, AbortError);
20
+ }
12
21
  for (var keys = Object.keys(obj), key = keys.pop(); key; key = keys.pop()) {
13
22
  this[key] = obj[key];
14
23
  }
15
24
  }
16
25
 
17
26
  function AggregateError (obj) {
18
- Error.captureStackTrace(this, this.constructor);
27
+ assert(obj, 'The options argument is required');
28
+ assert.strictEqual(typeof obj, 'object', 'The options argument has to be of type object');
29
+
30
+ AbortError.call(this, obj, ADD_STACKTRACE);
19
31
  Object.defineProperty(this, 'message', {
20
32
  value: obj.message || '',
21
33
  configurable: true,
22
34
  writable: true
23
35
  });
36
+ Error.captureStackTrace(this, AggregateError);
24
37
  for (var keys = Object.keys(obj), key = keys.pop(); key; key = keys.pop()) {
25
38
  this[key] = obj[key];
26
39
  }
27
40
  }
28
41
 
29
- util.inherits(AbortError, Error);
42
+ util.inherits(AbortError, RedisError);
30
43
  util.inherits(AggregateError, AbortError);
31
44
 
32
45
  Object.defineProperty(AbortError.prototype, 'name', {
33
46
  value: 'AbortError',
34
- // configurable: true,
47
+ configurable: true,
35
48
  writable: true
36
49
  });
37
50
  Object.defineProperty(AggregateError.prototype, 'name', {
38
51
  value: 'AggregateError',
39
- // configurable: true,
52
+ configurable: true,
40
53
  writable: true
41
54
  });
42
55
 
@@ -16,6 +16,7 @@ RedisClient.prototype.send_command = RedisClient.prototype.sendCommand = functio
16
16
  if (typeof command !== 'string') {
17
17
  throw new TypeError('Wrong input type "' + (command !== null && command !== undefined ? command.constructor.name : command) + '" for command name');
18
18
  }
19
+ command = command.toLowerCase();
19
20
  if (!Array.isArray(args)) {
20
21
  if (args === undefined || args === null) {
21
22
  args = [];
@@ -32,9 +33,9 @@ RedisClient.prototype.send_command = RedisClient.prototype.sendCommand = functio
32
33
 
33
34
  // Using the raw multi command is only possible with this function
34
35
  // If the command is not yet added to the client, the internal function should be called right away
35
- // Otherwise we need to redirect the calls to make sure the interal functions don't get skipped
36
+ // Otherwise we need to redirect the calls to make sure the internal functions don't get skipped
36
37
  // The internal functions could actually be used for any non hooked function
37
- // but this might change from time to time and at the moment there's no good way to distinguishe them
38
+ // but this might change from time to time and at the moment there's no good way to distinguish them
38
39
  // from each other, so let's just do it do it this way for the time being
39
40
  if (command === 'multi' || typeof this[command] !== 'function') {
40
41
  return this.internal_send_command(new Command(command, args, callback));
@@ -398,7 +398,7 @@ RedisClient.prototype.subscribe = RedisClient.prototype.SUBSCRIBE = function sub
398
398
  callback,
399
399
  i = 0;
400
400
  if (Array.isArray(arguments[0])) {
401
- arr = arguments[0];
401
+ arr = arguments[0].slice(0);
402
402
  callback = arguments[1];
403
403
  } else {
404
404
  len = arguments.length;
@@ -425,7 +425,7 @@ Multi.prototype.subscribe = Multi.prototype.SUBSCRIBE = function subscribe () {
425
425
  callback,
426
426
  i = 0;
427
427
  if (Array.isArray(arguments[0])) {
428
- arr = arguments[0];
428
+ arr = arguments[0].slice(0);
429
429
  callback = arguments[1];
430
430
  } else {
431
431
  len = arguments.length;
@@ -453,7 +453,7 @@ RedisClient.prototype.unsubscribe = RedisClient.prototype.UNSUBSCRIBE = function
453
453
  callback,
454
454
  i = 0;
455
455
  if (Array.isArray(arguments[0])) {
456
- arr = arguments[0];
456
+ arr = arguments[0].slice(0);
457
457
  callback = arguments[1];
458
458
  } else {
459
459
  len = arguments.length;
@@ -481,7 +481,7 @@ Multi.prototype.unsubscribe = Multi.prototype.UNSUBSCRIBE = function unsubscribe
481
481
  callback,
482
482
  i = 0;
483
483
  if (Array.isArray(arguments[0])) {
484
- arr = arguments[0];
484
+ arr = arguments[0].slice(0);
485
485
  callback = arguments[1];
486
486
  } else {
487
487
  len = arguments.length;
@@ -510,7 +510,7 @@ RedisClient.prototype.psubscribe = RedisClient.prototype.PSUBSCRIBE = function p
510
510
  callback,
511
511
  i = 0;
512
512
  if (Array.isArray(arguments[0])) {
513
- arr = arguments[0];
513
+ arr = arguments[0].slice(0);
514
514
  callback = arguments[1];
515
515
  } else {
516
516
  len = arguments.length;
@@ -537,7 +537,7 @@ Multi.prototype.psubscribe = Multi.prototype.PSUBSCRIBE = function psubscribe ()
537
537
  callback,
538
538
  i = 0;
539
539
  if (Array.isArray(arguments[0])) {
540
- arr = arguments[0];
540
+ arr = arguments[0].slice(0);
541
541
  callback = arguments[1];
542
542
  } else {
543
543
  len = arguments.length;
@@ -565,7 +565,7 @@ RedisClient.prototype.punsubscribe = RedisClient.prototype.PUNSUBSCRIBE = functi
565
565
  callback,
566
566
  i = 0;
567
567
  if (Array.isArray(arguments[0])) {
568
- arr = arguments[0];
568
+ arr = arguments[0].slice(0);
569
569
  callback = arguments[1];
570
570
  } else {
571
571
  len = arguments.length;
@@ -593,7 +593,7 @@ Multi.prototype.punsubscribe = Multi.prototype.PUNSUBSCRIBE = function punsubscr
593
593
  callback,
594
594
  i = 0;
595
595
  if (Array.isArray(arguments[0])) {
596
- arr = arguments[0];
596
+ arr = arguments[0].slice(0);
597
597
  callback = arguments[1];
598
598
  } else {
599
599
  len = arguments.length;
package/lib/utils.js CHANGED
@@ -127,7 +127,7 @@ module.exports = {
127
127
  reply_to_object: replyToObject,
128
128
  print: print,
129
129
  err_code: /^([A-Z]+)\s+(.+)$/,
130
- monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]{1,3} (.(?!\]))+.\]( ".+?")+$/,
130
+ monitor_regex: /^[0-9]{10,11}\.[0-9]+ \[[0-9]+ .+\]( ".+?")+$/,
131
131
  clone: convenienceClone,
132
132
  callback_or_emit: callbackOrEmit,
133
133
  reply_in_order: replyInOrder
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redis",
3
- "version": "2.6.4",
3
+ "version": "2.8.0",
4
4
  "description": "Redis client library",
5
5
  "keywords": [
6
6
  "database",
@@ -27,7 +27,7 @@
27
27
  "dependencies": {
28
28
  "double-ended-queue": "^2.1.0-0",
29
29
  "redis-commands": "^1.2.0",
30
- "redis-parser": "^2.0.0"
30
+ "redis-parser": "^2.6.0"
31
31
  },
32
32
  "engines": {
33
33
  "node": ">=0.10.0"
@@ -35,11 +35,11 @@
35
35
  "devDependencies": {
36
36
  "bluebird": "^3.0.2",
37
37
  "coveralls": "^2.11.2",
38
+ "eslint": "^4.2.0",
38
39
  "intercept-stdout": "~0.1.2",
39
- "eslint": "^3.5.0",
40
40
  "metrics": "^0.1.9",
41
- "mocha": "^2.3.2",
42
- "nyc": "^8.3.0",
41
+ "mocha": "^3.1.2",
42
+ "nyc": "^10.0.0",
43
43
  "tcp-port-used": "^0.1.2",
44
44
  "uuid": "^2.0.1",
45
45
  "win-spawn": "^2.0.0"