redis 3.0.1 → 3.1.2
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 +20 -16
- package/index.js +8 -19
- package/lib/createClient.js +5 -1
- package/lib/individualCommands.js +19 -7
- package/lib/utils.js +1 -1
- package/package.json +15 -13
package/README.md
CHANGED
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<a href="https://www.npmjs.com/package/redis"><img src="https://img.shields.io/npm/dm/redis.svg
|
|
13
|
-
<a href="https://www.npmjs.com/package/redis"><img src="https://img.shields.io/npm/v/redis.svg
|
|
14
|
-
<a href="https://
|
|
15
|
-
<a href="https://
|
|
16
|
-
<a href="https://coveralls.io/r/NodeRedis/node-redis?branch="><img src="https://coveralls.io/repos/NodeRedis/node-redis/badge.svg?
|
|
17
|
-
<a href="https://
|
|
12
|
+
<a href="https://www.npmjs.com/package/redis"><img src="https://img.shields.io/npm/dm/redis.svg" alt="NPM downloads"></a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/redis"><img src="https://img.shields.io/npm/v/redis.svg" alt="NPM version"></a>
|
|
14
|
+
<a href="https://github.com/NodeRedis/node-redis/actions?query=workflow%3ATests"><img src="https://github.com/NodeRedis/node-redis/workflows/Tests/badge.svg" alt="Build Status" /></a>
|
|
15
|
+
<a href="https://github.com/NodeRedis/node-redis/actions?query=workflow%3A%22Tests+Windows%22"><img src="https://github.com/NodeRedis/node-redis/workflows/Tests%20Windows/badge.svg" alt="Windows Build Status" /></a>
|
|
16
|
+
<a href="https://coveralls.io/r/NodeRedis/node-redis?branch="><img src="https://coveralls.io/repos/NodeRedis/node-redis/badge.svg?branch=master" alt="Coverage Status" /></a>
|
|
17
|
+
<a href="https://codeclimate.com/github/NodeRedis/node-redis/maintainability"><img src="https://api.codeclimate.com/v1/badges/f6d7063243c234237e73/maintainability" /></a>
|
|
18
|
+
<a href="https://lgtm.com/projects/g/NodeRedis/node-redis/context:javascript"><img src="https://img.shields.io/lgtm/grade/javascript/g/NodeRedis/node-redis.svg?logo=lgtm&logoWidth=18" alt="Coverage Status" /></a>
|
|
19
|
+
<a href="https://discord.gg/XMMVgxUm"><img src="https://img.shields.io/discord/697882427875393627?style=flat-square" /></a>
|
|
18
20
|
</p>
|
|
19
21
|
|
|
20
22
|
---
|
|
@@ -171,15 +173,16 @@ using unix sockets if possible to increase throughput.
|
|
|
171
173
|
| port | 6379 | Port of the Redis server |
|
|
172
174
|
| path | null | The UNIX socket string of the Redis server |
|
|
173
175
|
| url | null | The URL of the Redis server. Format: `[redis[s]:]//[[user][:password@]][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]` (More info avaliable at [IANA](http://www.iana.org/assignments/uri-schemes/prov/redis)). |
|
|
174
|
-
| string_numbers | null | Set to `true`, Node Redis will return Redis number values as Strings instead of javascript Numbers. Useful if you need to handle big numbers (above `Number.MAX_SAFE_INTEGER === 2^53`). Hiredis is incapable of this behavior, so setting this option to `true` will result in the built-in javascript parser being used no matter the value of the `parser` option.
|
|
176
|
+
| string_numbers | null | Set to `true`, Node Redis will return Redis number values as Strings instead of javascript Numbers. Useful if you need to handle big numbers (above `Number.MAX_SAFE_INTEGER === 2^53`). Hiredis is incapable of this behavior, so setting this option to `true` will result in the built-in javascript parser being used no matter the value of the `parser` option. |
|
|
175
177
|
| return_buffers | false | If set to `true`, then all replies will be sent to callbacks as Buffers instead of Strings. |
|
|
176
178
|
| detect_buffers | false | If set to `true`, then replies will be sent to callbacks as Buffers. This option lets you switch between Buffers and Strings on a per-command basis, whereas `return_buffers` applies to every command on a client. **Note**: This doesn't work properly with the pubsub mode. A subscriber has to either always return Strings or Buffers. |
|
|
177
179
|
| socket_keepalive | true | If set to `true`, the keep-alive functionality is enabled on the underlying socket. |
|
|
178
180
|
| socket_initial_delay | 0 | Initial Delay in milliseconds, and this will also behave the interval keep alive message sending to Redis. |
|
|
179
|
-
| no_ready_check | false | When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this, Node Redis has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. Setting `no_ready_check` to `true` will inhibit this check.
|
|
181
|
+
| no_ready_check | false | When a connection is established to the Redis server, the server might still be loading the database from disk. While loading, the server will not respond to any commands. To work around this, Node Redis has a "ready check" which sends the `INFO` command to the server. The response from the `INFO` command indicates whether the server is ready for more commands. When ready, `node_redis` emits a `ready` event. Setting `no_ready_check` to `true` will inhibit this check. |
|
|
180
182
|
| enable_offline_queue | true | By default, if there is no active connection to the Redis server, commands are added to a queue and are executed once the connection has been established. Setting `enable_offline_queue` to `false` will disable this feature and the callback will be executed immediately with an error, or an error will be emitted if no callback is specified. |
|
|
181
183
|
| retry_unfulfilled_commands | false | If set to `true`, all commands that were unfulfilled while the connection is lost will be retried after the connection has been reestablished. Use this with caution if you use state altering commands (e.g. `incr`). This is especially useful if you use blocking commands. |
|
|
182
|
-
| password | null | If set, client will run Redis auth command on connect. Alias `auth_pass` **Note** Node Redis < 2.5 must use `auth_pass`
|
|
184
|
+
| password | null | If set, client will run Redis auth command on connect. Alias `auth_pass` **Note** Node Redis < 2.5 must use `auth_pass` |
|
|
185
|
+
| user | null | The ACL user (only valid when `password` is set) |
|
|
183
186
|
| db | null | If set, client will run Redis `select` command on connect. |
|
|
184
187
|
| 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. |
|
|
185
188
|
| disable_resubscribing | false | If set to `true`, a client won't resubscribe after disconnecting. |
|
|
@@ -187,6 +190,7 @@ using unix sockets if possible to increase throughput.
|
|
|
187
190
|
| 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). |
|
|
188
191
|
| 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. |
|
|
189
192
|
| 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. |
|
|
193
|
+
| connect_timeout | 3600000 | In milliseconds. This should only be the timeout for connecting to redis, but for now it interferes with `retry_strategy` and stops it from reconnecting after this timeout. |
|
|
190
194
|
|
|
191
195
|
**`detect_buffers` example:**
|
|
192
196
|
|
|
@@ -394,7 +398,7 @@ responses using JavaScript syntax.
|
|
|
394
398
|
```js
|
|
395
399
|
client.hmset("key", "foo", "bar", "hello", "world");
|
|
396
400
|
|
|
397
|
-
client.hgetall("
|
|
401
|
+
client.hgetall("key", function(err, value) {
|
|
398
402
|
console.log(value.foo); // > "bar"
|
|
399
403
|
console.log(value.hello); // > "world"
|
|
400
404
|
});
|
|
@@ -638,7 +642,7 @@ client.watch("foo", function(watchError) {
|
|
|
638
642
|
* If err is null, it means Redis successfully attempted
|
|
639
643
|
* the operation.
|
|
640
644
|
*/
|
|
641
|
-
if (execError) throw
|
|
645
|
+
if (execError) throw execError;
|
|
642
646
|
|
|
643
647
|
/**
|
|
644
648
|
* If results === null, it means that a concurrent client
|
|
@@ -675,7 +679,7 @@ clients.watcher.watch("foo", function(watchError) {
|
|
|
675
679
|
|
|
676
680
|
// if you comment out the next line, the transaction will work
|
|
677
681
|
clients.modifier.set("foo", Math.random(), setError => {
|
|
678
|
-
if (setError) throw
|
|
682
|
+
if (setError) throw setError;
|
|
679
683
|
});
|
|
680
684
|
|
|
681
685
|
// using a setTimeout here to ensure that the MULTI/EXEC will come after the SET.
|
|
@@ -847,19 +851,19 @@ non-blocking ones may be queued up until after the blocking ones finish.
|
|
|
847
851
|
Another reason to use duplicate() is when multiple DBs on the same server are
|
|
848
852
|
accessed via the redis SELECT command. Each DB could use its own connection.
|
|
849
853
|
|
|
850
|
-
### `client.
|
|
854
|
+
### `client.sendCommand(command_name[, [args][, callback]])`
|
|
851
855
|
|
|
852
856
|
All Redis commands have been added to the `client` object. However, if new
|
|
853
857
|
commands are introduced before this library is updated or if you want to add
|
|
854
|
-
individual commands you can use `
|
|
858
|
+
individual commands you can use `sendCommand()` to send arbitrary commands to
|
|
855
859
|
Redis.
|
|
856
860
|
|
|
857
861
|
All commands are sent as multi-bulk commands. `args` can either be an Array of
|
|
858
862
|
arguments, or omitted / set to undefined.
|
|
859
863
|
|
|
860
|
-
### `redis.
|
|
864
|
+
### `redis.addCommand(command_name)`
|
|
861
865
|
|
|
862
|
-
Calling
|
|
866
|
+
Calling addCommand will add a new command to the prototype. The exact command
|
|
863
867
|
name will be used when calling using this new command. Using arbitrary arguments
|
|
864
868
|
is possible as with any other command.
|
|
865
869
|
|
package/index.js
CHANGED
|
@@ -109,6 +109,7 @@ function RedisClient (options, stream) {
|
|
|
109
109
|
this.closing = false;
|
|
110
110
|
this.server_info = {};
|
|
111
111
|
this.auth_pass = options.auth_pass || options.password;
|
|
112
|
+
this.auth_user = options.auth_user || options.user;
|
|
112
113
|
this.selected_db = options.db; // Save the selected db here, used when reconnecting
|
|
113
114
|
this.fire_strings = true; // Determine if strings or buffers should be written to the stream
|
|
114
115
|
this.pipeline = false;
|
|
@@ -240,7 +241,7 @@ RedisClient.prototype.create_stream = function () {
|
|
|
240
241
|
if (this.auth_pass !== undefined) {
|
|
241
242
|
this.ready = true;
|
|
242
243
|
// Fail silently as we might not be able to connect
|
|
243
|
-
this.auth(this.auth_pass, function (err) {
|
|
244
|
+
this.auth(this.auth_pass, this.auth_user, function (err) {
|
|
244
245
|
if (err && err.code !== 'UNCERTAIN_STATE') {
|
|
245
246
|
self.emit('error', err);
|
|
246
247
|
}
|
|
@@ -556,12 +557,8 @@ RedisClient.prototype.connection_gone = function (why, error) {
|
|
|
556
557
|
if (this.retry_delay instanceof Error) {
|
|
557
558
|
error = this.retry_delay;
|
|
558
559
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
errorMessage += 'connection timeout exceeded.';
|
|
562
|
-
} else {
|
|
563
|
-
errorMessage += 'maximum connection attempts exceeded.';
|
|
564
|
-
}
|
|
560
|
+
|
|
561
|
+
var errorMessage = 'Redis connection in broken state: retry aborted.';
|
|
565
562
|
|
|
566
563
|
this.flush_and_error({
|
|
567
564
|
message: errorMessage,
|
|
@@ -581,13 +578,7 @@ RedisClient.prototype.connection_gone = function (why, error) {
|
|
|
581
578
|
}
|
|
582
579
|
|
|
583
580
|
if (this.retry_totaltime >= this.connect_timeout) {
|
|
584
|
-
var message = 'Redis connection in broken state: ';
|
|
585
|
-
if (this.retry_totaltime >= this.connect_timeout) {
|
|
586
|
-
message += 'connection timeout exceeded.';
|
|
587
|
-
} else {
|
|
588
|
-
message += 'maximum connection attempts exceeded.';
|
|
589
|
-
}
|
|
590
|
-
|
|
581
|
+
var message = 'Redis connection in broken state: connection timeout exceeded.';
|
|
591
582
|
this.flush_and_error({
|
|
592
583
|
message: message,
|
|
593
584
|
code: 'CONNECTION_BROKEN',
|
|
@@ -864,11 +855,9 @@ RedisClient.prototype.internal_send_command = function (command_obj) {
|
|
|
864
855
|
if (command_obj.args && command_obj.args.length) {
|
|
865
856
|
undefinedArgError.args = command_obj.args;
|
|
866
857
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
}
|
|
871
|
-
throw undefinedArgError;
|
|
858
|
+
// there is always a callback in this scenario
|
|
859
|
+
command_obj.callback(undefinedArgError);
|
|
860
|
+
return false;
|
|
872
861
|
} else {
|
|
873
862
|
// Seems like numbers are converted fast using string concatenation
|
|
874
863
|
args_copy[i] = '' + args[i];
|
package/lib/createClient.js
CHANGED
|
@@ -29,7 +29,11 @@ module.exports = function createClient (port_arg, host_arg, options) {
|
|
|
29
29
|
// [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
|
|
30
30
|
if (parsed.slashes) { // We require slashes
|
|
31
31
|
if (parsed.auth) {
|
|
32
|
-
|
|
32
|
+
var columnIndex = parsed.auth.indexOf(':');
|
|
33
|
+
options.password = parsed.auth.slice(columnIndex + 1);
|
|
34
|
+
if (columnIndex > 0) {
|
|
35
|
+
options.user = parsed.auth.slice(0, columnIndex);
|
|
36
|
+
}
|
|
33
37
|
}
|
|
34
38
|
if (parsed.protocol) {
|
|
35
39
|
if (parsed.protocol === 'rediss:') {
|
|
@@ -4,7 +4,7 @@ var utils = require('./utils');
|
|
|
4
4
|
var debug = require('./debug');
|
|
5
5
|
var Multi = require('./multi');
|
|
6
6
|
var Command = require('./command');
|
|
7
|
-
var no_password_is_set = /no password is set/;
|
|
7
|
+
var no_password_is_set = /no password is set|called without any password configured/;
|
|
8
8
|
var loading = /LOADING/;
|
|
9
9
|
var RedisClient = require('../').RedisClient;
|
|
10
10
|
|
|
@@ -180,7 +180,7 @@ Multi.prototype.info = Multi.prototype.INFO = function info (section, callback)
|
|
|
180
180
|
return this;
|
|
181
181
|
};
|
|
182
182
|
|
|
183
|
-
function auth_callback (self, pass, callback) {
|
|
183
|
+
function auth_callback (self, pass, user, callback) {
|
|
184
184
|
return function (err, res) {
|
|
185
185
|
if (err) {
|
|
186
186
|
if (no_password_is_set.test(err.message)) {
|
|
@@ -191,7 +191,7 @@ function auth_callback (self, pass, callback) {
|
|
|
191
191
|
// If redis is still loading the db, it will not authenticate and everything else will fail
|
|
192
192
|
debug('Redis still loading, trying to authenticate later');
|
|
193
193
|
setTimeout(function () {
|
|
194
|
-
self.auth(pass, callback);
|
|
194
|
+
self.auth(pass, user, callback);
|
|
195
195
|
}, 100);
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
@@ -200,25 +200,37 @@ function auth_callback (self, pass, callback) {
|
|
|
200
200
|
};
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, callback) {
|
|
203
|
+
RedisClient.prototype.auth = RedisClient.prototype.AUTH = function auth (pass, user, callback) {
|
|
204
204
|
debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
|
|
205
205
|
|
|
206
|
+
// Backward compatibility support for auth with password only
|
|
207
|
+
if (user instanceof Function) {
|
|
208
|
+
callback = user;
|
|
209
|
+
user = null;
|
|
210
|
+
}
|
|
206
211
|
// Stash auth for connect and reconnect.
|
|
207
212
|
this.auth_pass = pass;
|
|
213
|
+
this.auth_user = user;
|
|
208
214
|
var ready = this.ready;
|
|
209
215
|
this.ready = ready || this.offline_queue.length === 0;
|
|
210
|
-
var tmp = this.internal_send_command(new Command('auth', [pass], auth_callback(this, pass, callback)));
|
|
216
|
+
var tmp = this.internal_send_command(new Command('auth', user ? [user, pass] : [pass], auth_callback(this, pass, user, callback)));
|
|
211
217
|
this.ready = ready;
|
|
212
218
|
return tmp;
|
|
213
219
|
};
|
|
214
220
|
|
|
215
221
|
// Only works with batch, not in a transaction
|
|
216
|
-
Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, callback) {
|
|
222
|
+
Multi.prototype.auth = Multi.prototype.AUTH = function auth (pass, user, callback) {
|
|
217
223
|
debug('Sending auth to ' + this.address + ' id ' + this.connection_id);
|
|
218
224
|
|
|
225
|
+
// Backward compatibility support for auth with password only
|
|
226
|
+
if (user instanceof Function) {
|
|
227
|
+
callback = user;
|
|
228
|
+
user = null;
|
|
229
|
+
}
|
|
219
230
|
// Stash auth for connect and reconnect.
|
|
220
231
|
this.auth_pass = pass;
|
|
221
|
-
this.
|
|
232
|
+
this.auth_user = user;
|
|
233
|
+
this.queue.push(new Command('auth', user ? [user, pass] : [pass], auth_callback(this._client, pass, user, callback)));
|
|
222
234
|
return this;
|
|
223
235
|
};
|
|
224
236
|
|
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]+ .+\]
|
|
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": "3.
|
|
3
|
+
"version": "3.1.2",
|
|
4
4
|
"description": "A high performance Redis client.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"database",
|
|
@@ -30,31 +30,33 @@
|
|
|
30
30
|
"coveralls": "nyc report --reporter=text-lcov | coveralls",
|
|
31
31
|
"coverage": "nyc report --reporter=html",
|
|
32
32
|
"benchmark": "node benchmarks/multi_bench.js",
|
|
33
|
-
"test": "nyc --cache mocha ./test/*.js ./test/commands/*.js --timeout=8000",
|
|
34
|
-
"lint": "eslint .
|
|
33
|
+
"test": "nyc --cache mocha ./test/*.spec.js ./test/commands/*.spec.js --timeout=8000 && npm run coverage",
|
|
34
|
+
"lint": "eslint .",
|
|
35
|
+
"lint:fix": "eslint . --fix",
|
|
36
|
+
"lint:report": "eslint --output-file=eslint-report.json --format=json .",
|
|
35
37
|
"compare": "node benchmarks/diff_multi_bench_output.js beforeBench.txt afterBench.txt"
|
|
36
38
|
},
|
|
37
39
|
"dependencies": {
|
|
38
|
-
"denque": "^1.
|
|
39
|
-
"redis-commands": "^1.
|
|
40
|
+
"denque": "^1.5.0",
|
|
41
|
+
"redis-commands": "^1.7.0",
|
|
40
42
|
"redis-errors": "^1.2.0",
|
|
41
43
|
"redis-parser": "^3.0.0"
|
|
42
44
|
},
|
|
43
45
|
"engines": {
|
|
44
|
-
"node": ">=
|
|
46
|
+
"node": ">=10"
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
47
|
-
"prettier": "^1.19.1",
|
|
48
49
|
"bluebird": "^3.7.2",
|
|
49
|
-
"coveralls": "^
|
|
50
|
-
"
|
|
50
|
+
"coveralls": "^3.1.0",
|
|
51
|
+
"cross-spawn": "^7.0.3",
|
|
52
|
+
"eslint": "^7.21.0",
|
|
51
53
|
"intercept-stdout": "~0.1.2",
|
|
52
54
|
"metrics": "^0.1.21",
|
|
53
|
-
"mocha": "^
|
|
54
|
-
"nyc": "^
|
|
55
|
+
"mocha": "^8.3.0",
|
|
56
|
+
"nyc": "^15.1.0",
|
|
57
|
+
"prettier": "^2.2.1",
|
|
55
58
|
"tcp-port-used": "^1.0.1",
|
|
56
|
-
"uuid": "^3.
|
|
57
|
-
"cross-spawn": "^6.0.5"
|
|
59
|
+
"uuid": "^8.3.2"
|
|
58
60
|
},
|
|
59
61
|
"repository": {
|
|
60
62
|
"type": "git",
|