redis 2.6.3 → 2.7.1
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 +12 -7
- package/changelog.md +30 -0
- package/index.js +15 -10
- package/lib/customErrors.js +19 -6
- package/lib/utils.js +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -197,7 +197,7 @@ __Tip:__ If the Redis server runs on the same machine as the client consider usi
|
|
|
197
197
|
| db | null | If set, client will run Redis `select` command on connect. |
|
|
198
198
|
| 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
199
|
| 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. |
|
|
200
|
+
| 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
201
|
| 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
202
|
| 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
203
|
| 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. |
|
|
@@ -224,7 +224,7 @@ retry_strategy example
|
|
|
224
224
|
```js
|
|
225
225
|
var client = redis.createClient({
|
|
226
226
|
retry_strategy: function (options) {
|
|
227
|
-
if (options.error.code === 'ECONNREFUSED') {
|
|
227
|
+
if (options.error && options.error.code === 'ECONNREFUSED') {
|
|
228
228
|
// End reconnecting on a specific error and flush all commands with a individual error
|
|
229
229
|
return new Error('The server refused the connection');
|
|
230
230
|
}
|
|
@@ -237,7 +237,7 @@ var client = redis.createClient({
|
|
|
237
237
|
return undefined;
|
|
238
238
|
}
|
|
239
239
|
// reconnect after
|
|
240
|
-
return Math.
|
|
240
|
+
return Math.min(options.attempt * 100, 3000);
|
|
241
241
|
}
|
|
242
242
|
});
|
|
243
243
|
```
|
|
@@ -296,10 +296,15 @@ client.get("foo_rand000000000000", function (err, reply) {
|
|
|
296
296
|
|
|
297
297
|
## Error handling (>= v.2.6)
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
299
|
+
Currently the following error subclasses exist:
|
|
300
|
+
|
|
301
|
+
* `RedisError`: _All errors_ returned by the client
|
|
302
|
+
* `ReplyError` subclass of `RedisError`: All errors returned by __Redis__ itself
|
|
303
|
+
* `AbortError` subclass of `RedisError`: All commands that could not finish due to what ever reason
|
|
304
|
+
* `ParserError` subclass of `RedisError`: Returned in case of a parser error (this should not happen)
|
|
305
|
+
* `AggregateError` subclass of `AbortError`: Emitted in case multiple unresolved commands without callback got rejected in debug_mode instead of lots of `AbortError`s.
|
|
306
|
+
|
|
307
|
+
All error classes are exported by the module.
|
|
303
308
|
|
|
304
309
|
Example:
|
|
305
310
|
```js
|
package/changelog.md
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## v.2.7.1 - 14 Mar, 2017
|
|
5
|
+
|
|
6
|
+
Bugfixes
|
|
7
|
+
|
|
8
|
+
- Fixed monitor mode not working in combination with IPv6 (2.6.0 regression)
|
|
9
|
+
|
|
10
|
+
## v.2.7.0 - 11 Mar, 2017
|
|
11
|
+
|
|
12
|
+
Features
|
|
13
|
+
|
|
14
|
+
- All returned errors are from now a subclass of `RedisError`.
|
|
15
|
+
|
|
16
|
+
Bugfixes
|
|
17
|
+
|
|
18
|
+
- Fixed rename_commands not accepting `null` as value
|
|
19
|
+
- Fixed `AbortError`s and `AggregateError`s not showing the error message in the stack trace
|
|
20
|
+
|
|
21
|
+
## v.2.6.5 - 15 Jan, 2017
|
|
22
|
+
|
|
23
|
+
Bugfixes
|
|
24
|
+
|
|
25
|
+
- Fixed parser not being reset in case the redis connection closed ASAP for overcoming of output buffer limits
|
|
26
|
+
- Fixed parser reset if (p)message_buffer listener is attached
|
|
27
|
+
|
|
28
|
+
## v.2.6.4 - 12 Jan, 2017
|
|
29
|
+
|
|
30
|
+
Bugfixes
|
|
31
|
+
|
|
32
|
+
- Fixed monitor mode not working in combination with IPv6, sockets or lua scripts (2.6.0 regression)
|
|
33
|
+
|
|
4
34
|
## v.2.6.3 - 31 Oct, 2016
|
|
5
35
|
|
|
6
36
|
Bugfixes
|
package/index.js
CHANGED
|
@@ -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) {
|
|
@@ -791,9 +798,6 @@ function return_pub_sub (self, reply) {
|
|
|
791
798
|
}
|
|
792
799
|
|
|
793
800
|
RedisClient.prototype.return_reply = function (reply) {
|
|
794
|
-
// If in monitor mode, all normal commands are still working and we only want to emit the streamlined commands
|
|
795
|
-
// As this is not the average use case and monitor is expensive anyway, let's change the code here, to improve
|
|
796
|
-
// the average performance of all other commands in case of no monitor mode
|
|
797
801
|
if (this.monitoring) {
|
|
798
802
|
var replyStr;
|
|
799
803
|
if (this.buffers && Buffer.isBuffer(reply)) {
|
|
@@ -801,8 +805,7 @@ RedisClient.prototype.return_reply = function (reply) {
|
|
|
801
805
|
} else {
|
|
802
806
|
replyStr = reply;
|
|
803
807
|
}
|
|
804
|
-
//
|
|
805
|
-
// Therefore the monitor command has to finish before it catches further commands
|
|
808
|
+
// If in monitor mode, all normal commands are still working and we only want to emit the streamlined commands
|
|
806
809
|
if (typeof replyStr === 'string' && utils.monitor_regex.test(replyStr)) {
|
|
807
810
|
var timestamp = replyStr.slice(0, replyStr.indexOf(' '));
|
|
808
811
|
var args = replyStr.slice(replyStr.indexOf('"') + 1, -1).split('" "').map(function (elem) {
|
|
@@ -928,7 +931,7 @@ RedisClient.prototype.internal_send_command = function (command_obj) {
|
|
|
928
931
|
args_copy[i] = this.options.prefix + args_copy[i];
|
|
929
932
|
}
|
|
930
933
|
}
|
|
931
|
-
if (
|
|
934
|
+
if (this.options.rename_commands && this.options.rename_commands[command]) {
|
|
932
935
|
command = this.options.rename_commands[command];
|
|
933
936
|
}
|
|
934
937
|
// Always use 'Multi bulk commands', but if passed any Buffer args, then do multiple writes, one for each arg.
|
|
@@ -1084,6 +1087,8 @@ exports.RedisClient = RedisClient;
|
|
|
1084
1087
|
exports.print = utils.print;
|
|
1085
1088
|
exports.Multi = require('./lib/multi');
|
|
1086
1089
|
exports.AbortError = errorClasses.AbortError;
|
|
1090
|
+
exports.RedisError = Parser.RedisError;
|
|
1091
|
+
exports.ParserError = Parser.ParserError;
|
|
1087
1092
|
exports.ReplyError = Parser.ReplyError;
|
|
1088
1093
|
exports.AggregateError = errorClasses.AggregateError;
|
|
1089
1094
|
|
package/lib/customErrors.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
47
|
+
configurable: true,
|
|
35
48
|
writable: true
|
|
36
49
|
});
|
|
37
50
|
Object.defineProperty(AggregateError.prototype, 'name', {
|
|
38
51
|
value: 'AggregateError',
|
|
39
|
-
|
|
52
|
+
configurable: true,
|
|
40
53
|
writable: true
|
|
41
54
|
});
|
|
42
55
|
|
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": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "Redis client library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"database",
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
"coverage": "nyc report --reporter=html",
|
|
22
22
|
"benchmark": "node benchmarks/multi_bench.js",
|
|
23
23
|
"test": "nyc --cache mocha ./test/*.js ./test/commands/*.js --timeout=8000",
|
|
24
|
-
"
|
|
24
|
+
"lint": "eslint . --fix && npm run coverage",
|
|
25
25
|
"compare": "node benchmarks/diff_multi_bench_output.js beforeBench.txt afterBench.txt"
|
|
26
26
|
},
|
|
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.5.0"
|
|
31
31
|
},
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=0.10.0"
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"bluebird": "^3.0.2",
|
|
37
37
|
"coveralls": "^2.11.2",
|
|
38
38
|
"intercept-stdout": "~0.1.2",
|
|
39
|
-
"eslint": "^
|
|
39
|
+
"eslint": "^3.5.0",
|
|
40
40
|
"metrics": "^0.1.9",
|
|
41
|
-
"mocha": "^
|
|
41
|
+
"mocha": "^3.1.2",
|
|
42
42
|
"nyc": "^8.3.0",
|
|
43
43
|
"tcp-port-used": "^0.1.2",
|
|
44
44
|
"uuid": "^2.0.1",
|