redis 2.7.1 → 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 +252 -132
- package/changelog.md +31 -19
- package/index.js +10 -3
- package/lib/commands.js +14 -6
- package/lib/createClient.js +3 -2
- package/lib/extendedApi.js +3 -2
- package/lib/individualCommands.js +8 -8
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@ redis - a node.js redis client
|
|
|
6
6
|
[](https://ci.appveyor.com/project/BridgeAR/node-redis/branch/master)
|
|
7
7
|
[](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
|
|
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,
|
|
52
|
-
From v.2.6 on the API supports camelCase and
|
|
53
|
-
|
|
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
|
|
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
|
|
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
|
|
115
|
-
|
|
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
|
|
126
|
-
then replayed just before this event is
|
|
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
|
|
135
|
-
are passed an object containing `delay`
|
|
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
|
|
140
|
-
|
|
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
|
|
151
|
-
writable. This event can be used to stream commands in to
|
|
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
|
|
154
|
-
That way you can decide when to reduce your
|
|
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
|
|
157
|
-
If false is returned the stream had to
|
|
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
|
|
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
|
|
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
|
|
169
|
-
port and host are probably fine and you don't need to supply any
|
|
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
|
|
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 |
|
|
@@ -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
|
|
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
|
|
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.
|
|
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`
|
|
248
|
-
first command after connecting. This can be tricky
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
`
|
|
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
|
|
261
|
-
|
|
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
|
|
266
|
-
If this is called while reconnecting
|
|
267
|
-
|
|
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
|
|
272
|
-
If you want to exit cleanly, call
|
|
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
|
|
275
|
-
If you set flush to false all still running commands
|
|
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
|
|
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"),
|
|
@@ -300,9 +346,13 @@ Currently the following error subclasses exist:
|
|
|
300
346
|
|
|
301
347
|
* `RedisError`: _All errors_ returned by the client
|
|
302
348
|
* `ReplyError` subclass of `RedisError`: All errors returned by __Redis__ itself
|
|
303
|
-
* `AbortError` subclass of `RedisError`: All commands that could not finish due
|
|
304
|
-
|
|
305
|
-
* `
|
|
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.
|
|
306
356
|
|
|
307
357
|
All error classes are exported by the module.
|
|
308
358
|
|
|
@@ -316,10 +366,11 @@ client.on('error', function (err) {
|
|
|
316
366
|
assert(err instanceof Error);
|
|
317
367
|
assert(err instanceof redis.AbortError);
|
|
318
368
|
assert(err instanceof redis.AggregateError);
|
|
319
|
-
|
|
369
|
+
// The set and get get aggregated in here
|
|
370
|
+
assert.strictEqual(err.errors.length, 2);
|
|
320
371
|
assert.strictEqual(err.code, 'NR_CLOSED');
|
|
321
372
|
});
|
|
322
|
-
client.set('foo', 123, 'bar', function (err, res) { //
|
|
373
|
+
client.set('foo', 123, 'bar', function (err, res) { // Too many arguments
|
|
323
374
|
assert(err instanceof redis.ReplyError); // => true
|
|
324
375
|
assert.strictEqual(err.command, 'SET');
|
|
325
376
|
assert.deepStrictEqual(err.args, ['foo', 123, 'bar']);
|
|
@@ -328,7 +379,8 @@ client.set('foo', 123, 'bar', function (err, res) { // To many arguments
|
|
|
328
379
|
client.set('foo', 'bar');
|
|
329
380
|
client.get('foo');
|
|
330
381
|
process.nextTick(function () {
|
|
331
|
-
|
|
382
|
+
// Force closing the connection while the command did not yet return
|
|
383
|
+
client.end(true);
|
|
332
384
|
redis.debug_mode = false;
|
|
333
385
|
});
|
|
334
386
|
});
|
|
@@ -337,25 +389,33 @@ client.set('foo', 123, 'bar', function (err, res) { // To many arguments
|
|
|
337
389
|
|
|
338
390
|
Every `ReplyError` contains the `command` name in all-caps and the arguments (`args`).
|
|
339
391
|
|
|
340
|
-
If node_redis emits a library error because of another error, the triggering
|
|
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.
|
|
341
394
|
|
|
342
395
|
___Error codes___
|
|
343
396
|
|
|
344
|
-
node_redis returns a `NR_CLOSED` error code if the clients connection dropped.
|
|
345
|
-
|
|
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.
|
|
346
401
|
|
|
347
402
|
## client.unref()
|
|
348
403
|
|
|
349
|
-
Call `unref()` on the underlying socket connection to the Redis server, allowing
|
|
404
|
+
Call `unref()` on the underlying socket connection to the Redis server, allowing
|
|
405
|
+
the program to exit once no more commands are pending.
|
|
350
406
|
|
|
351
|
-
This is an **experimental** feature, and only supports a subset of the Redis
|
|
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()`.
|
|
352
410
|
|
|
353
411
|
```js
|
|
354
412
|
var redis = require("redis")
|
|
355
413
|
var client = redis.createClient()
|
|
356
414
|
|
|
357
415
|
/*
|
|
358
|
-
Calling unref() will allow this program to exit immediately after the get
|
|
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.
|
|
359
419
|
*/
|
|
360
420
|
client.unref()
|
|
361
421
|
client.get("foo", function (err, value){
|
|
@@ -366,13 +426,15 @@ client.get("foo", function (err, value){
|
|
|
366
426
|
|
|
367
427
|
## Friendlier hash commands
|
|
368
428
|
|
|
369
|
-
Most Redis commands take a single String or an Array of Strings as arguments,
|
|
370
|
-
|
|
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.
|
|
371
432
|
|
|
372
433
|
### client.hgetall(hash, callback)
|
|
373
434
|
|
|
374
|
-
The reply from an HGETALL command will be converted into a JavaScript Object by
|
|
375
|
-
with the responses using JavaScript
|
|
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.
|
|
376
438
|
|
|
377
439
|
Example:
|
|
378
440
|
|
|
@@ -400,7 +462,8 @@ client.HMSET(key2, {
|
|
|
400
462
|
});
|
|
401
463
|
```
|
|
402
464
|
|
|
403
|
-
The properties and values of this Object will be set as keys and values in the
|
|
465
|
+
The properties and values of this Object will be set as keys and values in the
|
|
466
|
+
Redis hash.
|
|
404
467
|
|
|
405
468
|
### client.hmset(hash, key1, val1, ... keyn, valn, [callback])
|
|
406
469
|
|
|
@@ -440,11 +503,13 @@ sub.on("message", function (channel, message) {
|
|
|
440
503
|
sub.subscribe("a nice channel");
|
|
441
504
|
```
|
|
442
505
|
|
|
443
|
-
When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into
|
|
444
|
-
At that point, only commands that modify the subscription
|
|
445
|
-
set
|
|
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.
|
|
446
510
|
|
|
447
|
-
If you need to send regular commands to Redis while in subscriber mode, just
|
|
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()`).
|
|
448
513
|
|
|
449
514
|
## Subscriber Events
|
|
450
515
|
|
|
@@ -457,47 +522,57 @@ Listeners are passed the channel name as `channel` and the message as `message`.
|
|
|
457
522
|
|
|
458
523
|
### "pmessage" (pattern, channel, message)
|
|
459
524
|
|
|
460
|
-
Client will emit `pmessage` for every message received that matches an active
|
|
461
|
-
Listeners are passed the original pattern used with
|
|
462
|
-
|
|
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`.
|
|
463
529
|
|
|
464
530
|
### "message_buffer" (channel, message)
|
|
465
531
|
|
|
466
|
-
This is the same as the `message` event with the exception, that it is always
|
|
467
|
-
If you listen to the `message` event at the same time as
|
|
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.
|
|
468
535
|
|
|
469
536
|
### "pmessage_buffer" (pattern, channel, message)
|
|
470
537
|
|
|
471
|
-
This is the same as the `pmessage` event with the exception, that it is always
|
|
472
|
-
If you listen to the `pmessage` event at the same time
|
|
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.
|
|
473
541
|
|
|
474
542
|
### "subscribe" (channel, count)
|
|
475
543
|
|
|
476
|
-
Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are
|
|
477
|
-
channel name as `channel` and the new count of subscriptions for this
|
|
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`.
|
|
478
547
|
|
|
479
548
|
### "psubscribe" (pattern, count)
|
|
480
549
|
|
|
481
|
-
Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners
|
|
482
|
-
original pattern as `pattern`, and the new count of subscriptions
|
|
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`.
|
|
483
553
|
|
|
484
554
|
### "unsubscribe" (channel, count)
|
|
485
555
|
|
|
486
|
-
Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners
|
|
487
|
-
channel name as `channel` and the new count of subscriptions for
|
|
488
|
-
`count` is 0, this client has left subscriber mode
|
|
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.
|
|
489
560
|
|
|
490
561
|
### "punsubscribe" (pattern, count)
|
|
491
562
|
|
|
492
|
-
Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command.
|
|
493
|
-
channel name as `channel` and the new count of
|
|
494
|
-
`count` is 0, this client has
|
|
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.
|
|
495
567
|
|
|
496
568
|
## client.multi([commands])
|
|
497
569
|
|
|
498
|
-
`MULTI` commands are queued up until an `EXEC` is issued, and then all commands
|
|
499
|
-
Redis. The interface in `node_redis` is to return an
|
|
500
|
-
|
|
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)).
|
|
501
576
|
|
|
502
577
|
```js
|
|
503
578
|
var redis = require("./index"),
|
|
@@ -531,15 +606,20 @@ client.multi()
|
|
|
531
606
|
|
|
532
607
|
### Multi.exec([callback])
|
|
533
608
|
|
|
534
|
-
`client.multi()` is a constructor that returns a `Multi` object. `Multi` objects
|
|
535
|
-
same command methods as `client` objects do. Commands are
|
|
536
|
-
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.
|
|
537
612
|
|
|
538
|
-
If your code contains an syntax error an EXECABORT error is going to be thrown
|
|
539
|
-
|
|
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.
|
|
540
619
|
|
|
541
|
-
You can either chain together `MULTI` commands as in the above example, or you
|
|
542
|
-
commands while still sending regular client command as in
|
|
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:
|
|
543
623
|
|
|
544
624
|
```js
|
|
545
625
|
var redis = require("redis"),
|
|
@@ -559,8 +639,8 @@ multi.exec(function (err, replies) {
|
|
|
559
639
|
});
|
|
560
640
|
```
|
|
561
641
|
|
|
562
|
-
In addition to adding commands to the `MULTI` queue individually, you can also
|
|
563
|
-
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:
|
|
564
644
|
|
|
565
645
|
```js
|
|
566
646
|
var redis = require("redis"),
|
|
@@ -577,26 +657,36 @@ client.multi([
|
|
|
577
657
|
|
|
578
658
|
### Multi.exec_atomic([callback])
|
|
579
659
|
|
|
580
|
-
Identical to Multi.exec but with the difference that executing a single command
|
|
660
|
+
Identical to Multi.exec but with the difference that executing a single command
|
|
661
|
+
will not use transactions.
|
|
581
662
|
|
|
582
663
|
## client.batch([commands])
|
|
583
664
|
|
|
584
|
-
Identical to .multi without transactions. This is recommended if you want to
|
|
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.
|
|
585
667
|
|
|
586
|
-
`BATCH` commands are queued up until an `EXEC` is issued, and then all commands
|
|
587
|
-
Redis. The interface in `node_redis` is to return an
|
|
588
|
-
|
|
589
|
-
|
|
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.
|
|
590
674
|
|
|
591
|
-
If you fire many commands at once this is going to boost the execution speed
|
|
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.
|
|
592
679
|
|
|
593
680
|
## Monitor mode
|
|
594
681
|
|
|
595
|
-
Redis supports the `MONITOR` command, which lets you see all commands received
|
|
596
|
-
across all client connections, including from other client
|
|
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.
|
|
597
685
|
|
|
598
|
-
A `monitor` event is going to be emitted for every command fired from any client
|
|
599
|
-
|
|
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.
|
|
600
690
|
|
|
601
691
|
Example:
|
|
602
692
|
|
|
@@ -618,10 +708,11 @@ Some other things you might like to know about.
|
|
|
618
708
|
|
|
619
709
|
## client.server_info
|
|
620
710
|
|
|
621
|
-
After the ready probe completes, the results from the INFO command are saved in
|
|
622
|
-
object.
|
|
711
|
+
After the ready probe completes, the results from the INFO command are saved in
|
|
712
|
+
the `client.server_info` object.
|
|
623
713
|
|
|
624
|
-
The `versions` key contains an array of the elements of the version string for
|
|
714
|
+
The `versions` key contains an array of the elements of the version string for
|
|
715
|
+
easy comparison.
|
|
625
716
|
|
|
626
717
|
> client.server_info.redis_version
|
|
627
718
|
'2.3.0'
|
|
@@ -660,12 +751,15 @@ the second word as first parameter:
|
|
|
660
751
|
|
|
661
752
|
## client.duplicate([options][, callback])
|
|
662
753
|
|
|
663
|
-
Duplicate all current options and return a new redisClient instance. All options
|
|
664
|
-
|
|
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.
|
|
665
759
|
|
|
666
|
-
One example of when to use duplicate() would be to
|
|
760
|
+
One example of when to use duplicate() would be to accommodate the connection-
|
|
667
761
|
blocking redis commands BRPOP, BLPOP, and BRPOPLPUSH. If these commands
|
|
668
|
-
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
|
|
669
763
|
non-blocking ones may be queued up until after the blocking ones finish.
|
|
670
764
|
|
|
671
765
|
var Redis=require('redis');
|
|
@@ -686,17 +780,25 @@ non-blocking ones may be queued up until after the blocking ones finish.
|
|
|
686
780
|
};
|
|
687
781
|
get();
|
|
688
782
|
brpop();
|
|
689
|
-
|
|
690
|
-
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
|
|
691
785
|
accessed via the redis SELECT command. Each DB could use its own connection.
|
|
692
|
-
|
|
786
|
+
|
|
693
787
|
## client.send_command(command_name[, [args][, callback]])
|
|
694
788
|
|
|
695
|
-
All Redis commands have been added to the `client` object. However, if new
|
|
696
|
-
|
|
697
|
-
|
|
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.
|
|
698
793
|
|
|
699
|
-
All commands are sent as multi-bulk commands. `args` can either be an Array of
|
|
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.
|
|
700
802
|
|
|
701
803
|
## client.connected
|
|
702
804
|
|
|
@@ -704,19 +806,23 @@ Boolean tracking the state of the connection to the Redis server.
|
|
|
704
806
|
|
|
705
807
|
## client.command_queue_length
|
|
706
808
|
|
|
707
|
-
The number of commands that have been sent to the Redis server but not yet
|
|
708
|
-
enforce some kind of maximum queue depth for
|
|
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.
|
|
709
812
|
|
|
710
813
|
## client.offline_queue_length
|
|
711
814
|
|
|
712
|
-
The number of commands that have been queued up for a future connection. You can
|
|
713
|
-
some kind of maximum queue depth for pre-connection
|
|
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.
|
|
714
818
|
|
|
715
819
|
### Commands with Optional and Keyword arguments
|
|
716
820
|
|
|
717
|
-
This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset
|
|
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.
|
|
718
823
|
|
|
719
824
|
Example:
|
|
825
|
+
|
|
720
826
|
```js
|
|
721
827
|
var args = [ 'myzset', 1, 'one', 2, 'two', 3, 'three', 99, 'ninety-nine' ];
|
|
722
828
|
client.zadd(args, function (err, response) {
|
|
@@ -789,10 +895,13 @@ clients: 1, NodeJS: 6.2.0, Redis: 3.2.0, parser: javascript, connected by: tcp
|
|
|
789
895
|
|
|
790
896
|
To get debug output run your `node_redis` application with `NODE_DEBUG=redis`.
|
|
791
897
|
|
|
792
|
-
This is also going to result in good stack traces opposed to useless ones
|
|
793
|
-
|
|
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`).
|
|
794
902
|
|
|
795
|
-
Good stack traces are only activated in development and debug mode as this
|
|
903
|
+
Good stack traces are only activated in development and debug mode as this
|
|
904
|
+
results in a significant performance penalty.
|
|
796
905
|
|
|
797
906
|
___Comparison___:
|
|
798
907
|
Useless stack trace:
|
|
@@ -828,7 +937,8 @@ The original author of node_redis is [Matthew Ranney](https://github.com/mranney
|
|
|
828
937
|
|
|
829
938
|
The current lead maintainer is [Ruben Bridgewater](https://github.com/BridgeAR)
|
|
830
939
|
|
|
831
|
-
Many [others](https://github.com/NodeRedis/node_redis/graphs/contributors)
|
|
940
|
+
Many [others](https://github.com/NodeRedis/node_redis/graphs/contributors)
|
|
941
|
+
contributed to `node_redis` too. Thanks to all of them!
|
|
832
942
|
|
|
833
943
|
## License
|
|
834
944
|
|
|
@@ -836,10 +946,20 @@ Many [others](https://github.com/NodeRedis/node_redis/graphs/contributors) contr
|
|
|
836
946
|
|
|
837
947
|
### Consolidation: It's time for celebration
|
|
838
948
|
|
|
839
|
-
Right now there are two great redis clients around and both have some advantages
|
|
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.
|
|
840
954
|
|
|
841
|
-
First of all, we want to split small parts of our libraries into others so that
|
|
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.
|
|
842
960
|
|
|
843
|
-
We're very happy about this step towards working together as we both want to
|
|
961
|
+
We're very happy about this step towards working together as we both want to
|
|
962
|
+
give you the best redis experience possible.
|
|
844
963
|
|
|
845
|
-
If you want to join our cause by help maintaining something, please don't
|
|
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,54 +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
|
|
3
15
|
|
|
4
16
|
## v.2.7.1 - 14 Mar, 2017
|
|
5
17
|
|
|
6
18
|
Bugfixes
|
|
7
19
|
|
|
8
|
-
-
|
|
20
|
+
- Fixed monitor mode not working in combination with IPv6 (2.6.0 regression)
|
|
9
21
|
|
|
10
22
|
## v.2.7.0 - 11 Mar, 2017
|
|
11
23
|
|
|
12
24
|
Features
|
|
13
25
|
|
|
14
|
-
-
|
|
26
|
+
- All returned errors are from now a subclass of `RedisError`.
|
|
15
27
|
|
|
16
28
|
Bugfixes
|
|
17
29
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
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
|
|
20
32
|
|
|
21
33
|
## v.2.6.5 - 15 Jan, 2017
|
|
22
34
|
|
|
23
35
|
Bugfixes
|
|
24
36
|
|
|
25
|
-
-
|
|
26
|
-
-
|
|
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
|
|
27
39
|
|
|
28
40
|
## v.2.6.4 - 12 Jan, 2017
|
|
29
41
|
|
|
30
42
|
Bugfixes
|
|
31
43
|
|
|
32
|
-
-
|
|
44
|
+
- Fixed monitor mode not working in combination with IPv6, sockets or lua scripts (2.6.0 regression)
|
|
33
45
|
|
|
34
46
|
## v.2.6.3 - 31 Oct, 2016
|
|
35
47
|
|
|
36
48
|
Bugfixes
|
|
37
49
|
|
|
38
|
-
-
|
|
39
|
-
-
|
|
50
|
+
- Do not change the tls setting to camel_case
|
|
51
|
+
- Fix domain handling in combination with the offline queue (2.5.3 regression)
|
|
40
52
|
|
|
41
53
|
## v.2.6.2 - 16 Jun, 2016
|
|
42
54
|
|
|
43
55
|
Bugfixes
|
|
44
56
|
|
|
45
|
-
-
|
|
57
|
+
- Fixed individual callbacks of a transaction not being called (2.6.0 regression)
|
|
46
58
|
|
|
47
59
|
## v.2.6.1 - 02 Jun, 2016
|
|
48
60
|
|
|
49
61
|
Bugfixes
|
|
50
62
|
|
|
51
|
-
-
|
|
63
|
+
- Fixed invalid function name being exported
|
|
52
64
|
|
|
53
65
|
## v.2.6.0 - 01 Jun, 2016
|
|
54
66
|
|
|
@@ -130,7 +142,7 @@ Features
|
|
|
130
142
|
- Monitor and pub sub mode now work together with the offline queue
|
|
131
143
|
- All commands that were send after a connection loss are now going to be send after reconnecting
|
|
132
144
|
- Activating monitor mode does now work together with arbitrary commands including pub sub mode
|
|
133
|
-
- Pub sub mode is
|
|
145
|
+
- Pub sub mode is completely rewritten and all known issues fixed
|
|
134
146
|
- Added `string_numbers` option to get back strings instead of numbers
|
|
135
147
|
- Quit command is from now on always going to end the connection properly
|
|
136
148
|
|
|
@@ -173,7 +185,7 @@ Same changelog as the pre-release
|
|
|
173
185
|
|
|
174
186
|
## v.2.5.0-1 - 07 Mar, 2016
|
|
175
187
|
|
|
176
|
-
This is a big release with some
|
|
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.
|
|
177
189
|
|
|
178
190
|
It took way to long to release this one and the next release cycles will be shorter again.
|
|
179
191
|
|
|
@@ -193,7 +205,7 @@ Features
|
|
|
193
205
|
- Added a `warning` emitter that receives node_redis warnings like auth not required and deprecation messages
|
|
194
206
|
- Added a `retry_strategy` option that replaces all reconnect options
|
|
195
207
|
- The reconnecting event from now on also receives:
|
|
196
|
-
- The error message why the reconnect
|
|
208
|
+
- The error message why the reconnect happened (params.error)
|
|
197
209
|
- The amount of times the client was connected (params.times_connected)
|
|
198
210
|
- The total reconnecting time since the last time connected (params.total_retry_time)
|
|
199
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))
|
|
@@ -208,9 +220,9 @@ Bugfixes
|
|
|
208
220
|
- Fixed do not run toString on an array argument and throw a "invalid data" error instead
|
|
209
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
|
|
210
222
|
- The same applies to Map / Set and individual Object types
|
|
211
|
-
- Fixed redis url not accepting the protocol being omitted or protocols other than the redis protocol for
|
|
223
|
+
- Fixed redis url not accepting the protocol being omitted or protocols other than the redis protocol for convenience
|
|
212
224
|
- Fixed parsing the db keyspace even if the first database does not begin with a zero
|
|
213
|
-
- Fixed handling of errors
|
|
225
|
+
- Fixed handling of errors occurring while receiving pub sub messages
|
|
214
226
|
- Fixed huge string pipelines crashing NodeJS (Pipeline size above 256mb)
|
|
215
227
|
- Fixed rename_commands and prefix option not working together
|
|
216
228
|
- Fixed ready being emitted to early in case a slave is still syncing / master down
|
|
@@ -223,7 +235,7 @@ Deprecations
|
|
|
223
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.
|
|
224
236
|
- Using .end(flush) without the flush parameter is deprecated and the flush parameter should explicitly be used
|
|
225
237
|
- From v.3.0.0 on using .end without flush will result in an error
|
|
226
|
-
- Using .end without flush means that any command that did not yet return is going to silently fail. Therefor this is considered
|
|
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
|
|
227
239
|
- Depending on the return value of a command to detect the backpressure is deprecated
|
|
228
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
|
|
229
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
|
|
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
|
}
|
|
@@ -304,7 +304,12 @@ RedisClient.prototype.create_stream = function () {
|
|
|
304
304
|
// Fire the command before redis is connected to be sure it's the first fired command
|
|
305
305
|
if (this.auth_pass !== undefined) {
|
|
306
306
|
this.ready = true;
|
|
307
|
-
|
|
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
|
+
});
|
|
308
313
|
this.ready = false;
|
|
309
314
|
}
|
|
310
315
|
};
|
|
@@ -1095,4 +1100,6 @@ exports.AggregateError = errorClasses.AggregateError;
|
|
|
1095
1100
|
// Add all redis commands / node_redis api to the client
|
|
1096
1101
|
require('./lib/individualCommands');
|
|
1097
1102
|
require('./lib/extendedApi');
|
|
1098
|
-
|
|
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
|
-
|
|
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;
|
package/lib/createClient.js
CHANGED
|
@@ -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
|
|
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 =
|
|
63
|
+
options.path = url;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
} else if (typeof port_arg === 'object' || port_arg === undefined) {
|
package/lib/extendedApi.js
CHANGED
|
@@ -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
|
|
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
|
|
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redis",
|
|
3
|
-
"version": "2.
|
|
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.
|
|
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
41
|
"mocha": "^3.1.2",
|
|
42
|
-
"nyc": "^
|
|
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"
|