redis 3.1.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.
Files changed (47) hide show
  1. package/package.json +1 -1
  2. package/.deepsource.toml +0 -9
  3. package/heroku/index.js +0 -14
  4. package/heroku/node_modules/.package-lock.json +0 -57
  5. package/heroku/node_modules/denque/CHANGELOG.md +0 -4
  6. package/heroku/node_modules/denque/LICENSE +0 -13
  7. package/heroku/node_modules/denque/README.md +0 -362
  8. package/heroku/node_modules/denque/index.d.ts +0 -31
  9. package/heroku/node_modules/denque/index.js +0 -443
  10. package/heroku/node_modules/denque/package.json +0 -55
  11. package/heroku/node_modules/redis/.deepsource.toml +0 -9
  12. package/heroku/node_modules/redis/CHANGELOG.md +0 -880
  13. package/heroku/node_modules/redis/LICENSE +0 -24
  14. package/heroku/node_modules/redis/README.md +0 -1009
  15. package/heroku/node_modules/redis/a.js +0 -12
  16. package/heroku/node_modules/redis/index.js +0 -1039
  17. package/heroku/node_modules/redis/lib/command.js +0 -16
  18. package/heroku/node_modules/redis/lib/commands.js +0 -105
  19. package/heroku/node_modules/redis/lib/createClient.js +0 -88
  20. package/heroku/node_modules/redis/lib/customErrors.js +0 -58
  21. package/heroku/node_modules/redis/lib/debug.js +0 -13
  22. package/heroku/node_modules/redis/lib/extendedApi.js +0 -113
  23. package/heroku/node_modules/redis/lib/individualCommands.js +0 -629
  24. package/heroku/node_modules/redis/lib/multi.js +0 -187
  25. package/heroku/node_modules/redis/lib/utils.js +0 -134
  26. package/heroku/node_modules/redis/npm +0 -0
  27. package/heroku/node_modules/redis/package.json +0 -77
  28. package/heroku/node_modules/redis-commands/LICENSE +0 -22
  29. package/heroku/node_modules/redis-commands/README.md +0 -51
  30. package/heroku/node_modules/redis-commands/changelog.md +0 -83
  31. package/heroku/node_modules/redis-commands/commands.json +0 -2334
  32. package/heroku/node_modules/redis-commands/index.js +0 -168
  33. package/heroku/node_modules/redis-commands/package.json +0 -41
  34. package/heroku/node_modules/redis-commands/tools/build.js +0 -62
  35. package/heroku/node_modules/redis-errors/LICENSE +0 -22
  36. package/heroku/node_modules/redis-errors/README.md +0 -116
  37. package/heroku/node_modules/redis-errors/index.js +0 -7
  38. package/heroku/node_modules/redis-errors/lib/modern.js +0 -59
  39. package/heroku/node_modules/redis-errors/lib/old.js +0 -119
  40. package/heroku/node_modules/redis-errors/package.json +0 -41
  41. package/heroku/node_modules/redis-parser/LICENSE +0 -22
  42. package/heroku/node_modules/redis-parser/README.md +0 -166
  43. package/heroku/node_modules/redis-parser/changelog.md +0 -156
  44. package/heroku/node_modules/redis-parser/index.js +0 -3
  45. package/heroku/node_modules/redis-parser/lib/parser.js +0 -552
  46. package/heroku/node_modules/redis-parser/package.json +0 -53
  47. package/heroku/package.json +0 -9
@@ -1,1009 +0,0 @@
1
- <p align="center">
2
- <a href="https://github.com/noderedis/node-redis/">
3
- <img width="190px" src="https://static.invertase.io/assets/node_redis_logo.png" />
4
- </a>
5
- <h2 align="center">Node Redis</h2>
6
- <h4 align="center">A high performance Node.js Redis client.</h4>
7
- </p>
8
-
9
- ---
10
-
11
- <p align="center">
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://twitter.com/NodeRedis"><img src="https://img.shields.io/twitter/follow/NodeRedis.svg?style=flat-square&colorA=1da1f2&colorB=&label=Follow%20on%20Twitter" alt="Follow on Twitter"></a>
18
- <a href="https://codeclimate.com/github/NodeRedis/node-redis/maintainability"><img src="https://api.codeclimate.com/v1/badges/f6d7063243c234237e73/maintainability" /></a>
19
- <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>
20
- </p>
21
-
22
- ---
23
-
24
- ## Installation
25
-
26
- ```bash
27
- npm install redis
28
- ```
29
-
30
- ## Usage
31
-
32
- #### Example
33
-
34
- ```js
35
- const redis = require("redis");
36
- const client = redis.createClient();
37
-
38
- client.on("error", function(error) {
39
- console.error(error);
40
- });
41
-
42
- client.set("key", "value", redis.print);
43
- client.get("key", redis.print);
44
- ```
45
-
46
- Note that the API is entirely asynchronous. To get data back from the server,
47
- you'll need to use a callback.
48
-
49
- ### Promises
50
-
51
- Node Redis currently doesn't natively support promises (this is coming in v4), however you can wrap the methods you
52
- want to use with promises using the built-in Node.js `util.promisify` method on Node.js >= v8;
53
-
54
- ```js
55
- const { promisify } = require("util");
56
- const getAsync = promisify(client.get).bind(client);
57
-
58
- getAsync.then(console.log).catch(console.error);
59
- ```
60
-
61
- ### Commands
62
-
63
- This library is a 1 to 1 mapping of the [Redis commands](https://redis.io/commands).
64
-
65
- Each Redis command is exposed as a function on the `client` object.
66
- All functions take either an `args` Array plus optional `callback` Function or
67
- a variable number of individual arguments followed by an optional callback.
68
- Examples:
69
-
70
- ```js
71
- client.hmset(["key", "foo", "bar"], function(err, res) {
72
- // ...
73
- });
74
-
75
- // Works the same as
76
- client.hmset("key", ["foo", "bar"], function(err, res) {
77
- // ...
78
- });
79
-
80
- // Or
81
- client.hmset("key", "foo", "bar", function(err, res) {
82
- // ...
83
- });
84
- ```
85
-
86
- Care should be taken with user input if arrays are possible (via body-parser, query string or other method), as single arguments could be unintentionally interpreted as multiple args.
87
-
88
- Note that in either form the `callback` is optional:
89
-
90
- ```js
91
- client.set("foo", "bar");
92
- client.set(["hello", "world"]);
93
- ```
94
-
95
- If the key is missing, reply will be null. Only if the [Redis Command
96
- Reference](http://redis.io/commands) states something else it will not be null.
97
-
98
- ```js
99
- client.get("missing_key", function(err, reply) {
100
- // reply is null when the key is missing
101
- console.log(reply);
102
- });
103
- ```
104
-
105
- Minimal parsing is done on the replies. Commands that return a integer return
106
- JavaScript Numbers, arrays return JavaScript Array. `HGETALL` returns an Object
107
- keyed by the hash keys. All strings will either be returned as string or as
108
- buffer depending on your setting. Please be aware that sending null, undefined
109
- and Boolean values will result in the value coerced to a string!
110
-
111
- ## API
112
-
113
- ### Connection and other Events
114
-
115
- `client` will emit some events about the state of the connection to the Redis server.
116
-
117
- #### `"ready"`
118
-
119
- `client` will emit `ready` once a connection is established. Commands issued
120
- before the `ready` event are queued, then replayed just before this event is
121
- emitted.
122
-
123
- #### `"connect"`
124
-
125
- `client` will emit `connect` as soon as the stream is connected to the server.
126
-
127
- #### `"reconnecting"`
128
-
129
- `client` will emit `reconnecting` when trying to reconnect to the Redis server
130
- after losing the connection. Listeners are passed an object containing `delay`
131
- (in ms from the previous try) and `attempt` (the attempt #) attributes.
132
-
133
- #### `"error"`
134
-
135
- `client` will emit `error` when encountering an error connecting to the Redis
136
- server or when any other in Node Redis occurs. If you use a command without
137
- callback and encounter a ReplyError it is going to be emitted to the error
138
- listener.
139
-
140
- So please attach the error listener to Node Redis.
141
-
142
- #### `"end"`
143
-
144
- `client` will emit `end` when an established Redis server connection has closed.
145
-
146
- #### `"warning"`
147
-
148
- `client` will emit `warning` when password was set but none is needed and if a
149
- deprecated option / function / similar is used.
150
-
151
- ### redis.createClient()
152
-
153
- If you have `redis-server` running on the same machine as node, then the
154
- defaults for port and host are probably fine and you don't need to supply any
155
- arguments. `createClient()` returns a `RedisClient` object. Otherwise,
156
- `createClient()` accepts these arguments:
157
-
158
- - `redis.createClient([options])`
159
- - `redis.createClient(unix_socket[, options])`
160
- - `redis.createClient(redis_url[, options])`
161
- - `redis.createClient(port[, host][, options])`
162
-
163
- **Tip:** If the Redis server runs on the same machine as the client consider
164
- using unix sockets if possible to increase throughput.
165
-
166
- **Note:** Using `'rediss://...` for the protocol in a `redis_url` will enable a TLS socket connection. However, additional TLS options will need to be passed in `options`, if required.
167
-
168
- #### `options` object properties
169
-
170
- | Property | Default | Description |
171
- | -------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
172
- | host | 127.0.0.1 | IP address of the Redis server |
173
- | port | 6379 | Port of the Redis server |
174
- | path | null | The UNIX socket string of the Redis server |
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)). |
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. |
177
- | return_buffers | false | If set to `true`, then all replies will be sent to callbacks as Buffers instead of Strings. |
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. |
179
- | socket_keepalive | true | If set to `true`, the keep-alive functionality is enabled on the underlying socket. |
180
- | socket_initial_delay | 0 | Initial Delay in milliseconds, and this will also behave the interval keep alive message sending to Redis. |
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. |
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. |
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. |
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) |
186
- | db | null | If set, client will run Redis `select` command on connect. |
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. |
188
- | disable_resubscribing | false | If set to `true`, a client won't resubscribe after disconnecting. |
189
- | 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. |
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). |
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. |
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. |
194
-
195
- **`detect_buffers` example:**
196
-
197
- ```js
198
- const redis = require("redis");
199
- const client = redis.createClient({ detect_buffers: true });
200
-
201
- client.set("foo_rand000000000000", "OK");
202
-
203
- // This will return a JavaScript String
204
- client.get("foo_rand000000000000", function(err, reply) {
205
- console.log(reply.toString()); // Will print `OK`
206
- });
207
-
208
- // This will return a Buffer since original key is specified as a Buffer
209
- client.get(new Buffer("foo_rand000000000000"), function(err, reply) {
210
- console.log(reply.toString()); // Will print `<Buffer 4f 4b>`
211
- });
212
- ```
213
-
214
- **`retry_strategy` example:**
215
-
216
- ```js
217
- const client = redis.createClient({
218
- retry_strategy: function(options) {
219
- if (options.error && options.error.code === "ECONNREFUSED") {
220
- // End reconnecting on a specific error and flush all commands with
221
- // a individual error
222
- return new Error("The server refused the connection");
223
- }
224
- if (options.total_retry_time > 1000 * 60 * 60) {
225
- // End reconnecting after a specific timeout and flush all commands
226
- // with a individual error
227
- return new Error("Retry time exhausted");
228
- }
229
- if (options.attempt > 10) {
230
- // End reconnecting with built in error
231
- return undefined;
232
- }
233
- // reconnect after
234
- return Math.min(options.attempt * 100, 3000);
235
- },
236
- });
237
- ```
238
-
239
- ### client.auth(password[, callback])
240
-
241
- When connecting to a Redis server that requires authentication, the `AUTH`
242
- command must be sent as the first command after connecting. This can be tricky
243
- to coordinate with reconnections, the ready check, etc. To make this easier,
244
- `client.auth()` stashes `password` and will send it after each connection,
245
- including reconnections. `callback` is invoked only once, after the response to
246
- the very first `AUTH` command sent.
247
- NOTE: Your call to `client.auth()` should not be inside the ready handler. If
248
- you are doing this wrong, `client` will emit an error that looks
249
- something like this `Error: Ready check failed: ERR operation not permitted`.
250
-
251
- ### client.quit(callback)
252
-
253
- This sends the quit command to the redis server and ends cleanly right after all
254
- running commands were properly handled. If this is called while reconnecting
255
- (and therefore no connection to the redis server exists) it is going to end the
256
- connection right away instead of resulting in further reconnections! All offline
257
- commands are going to be flushed with an error in that case.
258
-
259
- ### client.end(flush)
260
-
261
- Forcibly close the connection to the Redis server. Note that this does not wait
262
- until all replies have been parsed. If you want to exit cleanly, call
263
- `client.quit()` as mentioned above.
264
-
265
- You should set flush to true, if you are not absolutely sure you do not care
266
- about any other commands. If you set flush to false all still running commands
267
- will silently fail.
268
-
269
- This example closes the connection to the Redis server before the replies have
270
- been read. You probably don't want to do this:
271
-
272
- ```js
273
- const redis = require("redis");
274
- const client = redis.createClient();
275
-
276
- client.set("hello", "world", function(err) {
277
- // This will either result in an error (flush parameter is set to true)
278
- // or will silently fail and this callback will not be called at all (flush set to false)
279
- console.error(err);
280
- });
281
-
282
- // No further commands will be processed
283
- client.end(true);
284
-
285
- client.get("hello", function(err) {
286
- console.error(err); // => 'The connection has already been closed.'
287
- });
288
- ```
289
-
290
- `client.end()` without the flush parameter set to true should NOT be used in production!
291
-
292
- ### Error Handling
293
-
294
- Currently the following `Error` subclasses exist:
295
-
296
- - `RedisError`: _All errors_ returned by the client
297
- - `ReplyError` subclass of `RedisError`: All errors returned by **Redis** itself
298
- - `AbortError` subclass of `RedisError`: All commands that could not finish due
299
- to what ever reason
300
- - `ParserError` subclass of `RedisError`: Returned in case of a parser error
301
- (this should not happen)
302
- - `AggregateError` subclass of `AbortError`: Emitted in case multiple unresolved
303
- commands without callback got rejected in debug_mode instead of lots of
304
- `AbortError`s.
305
-
306
- All error classes are exported by the module.
307
-
308
- #### Example
309
-
310
- ```js
311
- const assert = require("assert");
312
-
313
- const redis = require("redis");
314
- const { AbortError, AggregateError, ReplyError } = require("redis");
315
-
316
- const client = redis.createClient();
317
-
318
- client.on("error", function(err) {
319
- assert(err instanceof Error);
320
- assert(err instanceof AbortError);
321
- assert(err instanceof AggregateError);
322
-
323
- // The set and get are aggregated in here
324
- assert.strictEqual(err.errors.length, 2);
325
- assert.strictEqual(err.code, "NR_CLOSED");
326
- });
327
-
328
- client.set("foo", "bar", "baz", function(err, res) {
329
- // Too many arguments
330
- assert(err instanceof ReplyError); // => true
331
- assert.strictEqual(err.command, "SET");
332
- assert.deepStrictEqual(err.args, ["foo", 123, "bar"]);
333
-
334
- redis.debug_mode = true;
335
-
336
- client.set("foo", "bar");
337
- client.get("foo");
338
-
339
- process.nextTick(function() {
340
- // Force closing the connection while the command did not yet return
341
- client.end(true);
342
- redis.debug_mode = false;
343
- });
344
- });
345
- ```
346
-
347
- Every `ReplyError` contains the `command` name in all-caps and the arguments (`args`).
348
-
349
- If Node Redis emits a library error because of another error, the triggering
350
- error is added to the returned error as `origin` attribute.
351
-
352
- **_Error codes_**
353
-
354
- Node Redis returns a `NR_CLOSED` error code if the clients connection dropped.
355
- If a command unresolved command got rejected a `UNCERTAIN_STATE` code is
356
- returned. A `CONNECTION_BROKEN` error code is used in case Node Redis gives up
357
- to reconnect.
358
-
359
- ### client.unref()
360
-
361
- Call `unref()` on the underlying socket connection to the Redis server, allowing
362
- the program to exit once no more commands are pending.
363
-
364
- This is an **experimental** feature, and only supports a subset of the Redis
365
- protocol. Any commands where client state is saved on the Redis server, e.g.
366
- `*SUBSCRIBE` or the blocking `BL*` commands will _NOT_ work with `.unref()`.
367
-
368
- ```js
369
- const redis = require("redis");
370
- const client = redis.createClient();
371
-
372
- /*
373
- * Calling unref() will allow this program to exit immediately after the get
374
- * command finishes. Otherwise the client would hang as long as the
375
- * client-server connection is alive.
376
- */
377
- client.unref();
378
-
379
- client.get("foo", function(err, value) {
380
- if (err) throw err;
381
- console.log(value);
382
- });
383
- ```
384
-
385
- ### Hash Commands
386
-
387
- Most Redis commands take a single String or an Array of Strings as arguments,
388
- and replies are sent back as a single String or an Array of Strings. When
389
- dealing with hash values, there are a couple of useful exceptions to this.
390
-
391
- #### client.hgetall(hash, callback)
392
-
393
- The reply from an `HGETALL` command will be converted into a JavaScript Object. That way you can interact with the
394
- responses using JavaScript syntax.
395
-
396
- **Example:**
397
-
398
- ```js
399
- client.hmset("key", "foo", "bar", "hello", "world");
400
-
401
- client.hgetall("key", function(err, value) {
402
- console.log(value.foo); // > "bar"
403
- console.log(value.hello); // > "world"
404
- });
405
- ```
406
-
407
- #### client.hmset(hash, key1, val1, ...keyN, valN, [callback])
408
-
409
- Multiple values may also be set by supplying more arguments.
410
-
411
- **Example:**
412
-
413
- ```js
414
- // key
415
- // 1) foo => bar
416
- // 2) hello => world
417
- client.HMSET("key", "foo", "bar", "hello", "world");
418
- ```
419
-
420
- ### PubSub
421
-
422
- #### Example
423
-
424
- This example opens two client connections, subscribes to a channel on one of them, and publishes to that
425
- channel on the other.
426
-
427
- ```js
428
- const redis = require("redis");
429
-
430
- const subscriber = redis.createClient();
431
- const publisher = redis.createClient();
432
-
433
- let messageCount = 0;
434
-
435
- subscriber.on("subscribe", function(channel, count) {
436
- publisher.publish("a channel", "a message");
437
- publisher.publish("a channel", "another message");
438
- });
439
-
440
- subscriber.on("message", function(channel, message) {
441
- messageCount += 1;
442
-
443
- console.log("Subscriber received message in channel '" + channel + "': " + message);
444
-
445
- if (messageCount === 2) {
446
- subscriber.unsubscribe();
447
- subscriber.quit();
448
- publisher.quit();
449
- }
450
- });
451
-
452
- subscriber.subscribe("a channel");
453
- ```
454
-
455
- When a client issues a `SUBSCRIBE` or `PSUBSCRIBE`, that connection is put into
456
- a `"subscriber"` mode. At that point, the only valid commands are those that modify the subscription
457
- set, and quit (also ping on some redis versions). When
458
- the subscription set is empty, the connection is put back into regular mode.
459
-
460
- If you need to send regular commands to Redis while in subscriber mode, just
461
- open another connection with a new client (use `client.duplicate()` to quickly duplicate an existing client).
462
-
463
- #### Subscriber Events
464
-
465
- If a client has subscriptions active, it may emit these events:
466
-
467
- **"message" (channel, message)**:
468
-
469
- Client will emit `message` for every message received that matches an active subscription.
470
- Listeners are passed the channel name as `channel` and the message as `message`.
471
-
472
- **"pmessage" (pattern, channel, message)**:
473
-
474
- Client will emit `pmessage` for every message received that matches an active
475
- subscription pattern. Listeners are passed the original pattern used with
476
- `PSUBSCRIBE` as `pattern`, the sending channel name as `channel`, and the
477
- message as `message`.
478
-
479
- **"message_buffer" (channel, message)**:
480
-
481
- This is the same as the `message` event with the exception, that it is always
482
- going to emit a buffer. If you listen to the `message` event at the same time as
483
- the `message_buffer`, it is always going to emit a string.
484
-
485
- **"pmessage_buffer" (pattern, channel, message)**:
486
-
487
- This is the same as the `pmessage` event with the exception, that it is always
488
- going to emit a buffer. If you listen to the `pmessage` event at the same time
489
- as the `pmessage_buffer`, it is always going to emit a string.
490
-
491
- **"subscribe" (channel, count)**:
492
-
493
- Client will emit `subscribe` in response to a `SUBSCRIBE` command. Listeners are
494
- passed the channel name as `channel` and the new count of subscriptions for this
495
- client as `count`.
496
-
497
- **"psubscribe" (pattern, count)**:
498
-
499
- Client will emit `psubscribe` in response to a `PSUBSCRIBE` command. Listeners
500
- are passed the original pattern as `pattern`, and the new count of subscriptions
501
- for this client as `count`.
502
-
503
- **"unsubscribe" (channel, count)**:
504
-
505
- Client will emit `unsubscribe` in response to a `UNSUBSCRIBE` command. Listeners
506
- are passed the channel name as `channel` and the new count of subscriptions for
507
- this client as `count`. When `count` is 0, this client has left subscriber mode
508
- and no more subscriber events will be emitted.
509
-
510
- **"punsubscribe" (pattern, count)**:
511
-
512
- Client will emit `punsubscribe` in response to a `PUNSUBSCRIBE` command.
513
- Listeners are passed the channel name as `channel` and the new count of
514
- subscriptions for this client as `count`. When `count` is 0, this client has
515
- left subscriber mode and no more subscriber events will be emitted.
516
-
517
- ### client.multi([commands])
518
-
519
- `MULTI` commands are queued up until an `EXEC` is issued, and then all commands
520
- are run atomically by Redis. The interface returns an
521
- individual `Multi` object by calling `client.multi()`. If any command fails to
522
- queue, all commands are rolled back and none is going to be executed (For
523
- further information see the [Redis transactions](http://redis.io/topics/transactions) documentation).
524
-
525
- ```js
526
- const redis = require("redis");
527
- const client = redis.createClient();
528
-
529
- let setSize = 20;
530
-
531
- client.sadd("key", "member1");
532
- client.sadd("key", "member2");
533
-
534
- while (setSize > 0) {
535
- client.sadd("key", "member" + setSize);
536
- setSize -= 1;
537
- }
538
-
539
- // chain commands
540
- client
541
- .multi()
542
- .scard("key")
543
- .smembers("key")
544
- .keys("*")
545
- .dbsize()
546
- .exec(function(err, replies) {
547
- console.log("MULTI got " + replies.length + " replies");
548
- replies.forEach(function(reply, index) {
549
- console.log("REPLY @ index " + index + ": " + reply.toString());
550
- });
551
- });
552
- ```
553
-
554
- #### Multi.exec([callback])
555
-
556
- `client.multi()` is a constructor that returns a `Multi` object. `Multi` objects
557
- share all of the same command methods as `client` objects do. Commands are
558
- queued up inside the `Multi` object until `Multi.exec()` is invoked.
559
-
560
- If your code contains an syntax error an `EXECABORT` error is going to be thrown
561
- and all commands are going to be aborted. That error contains a `.errors`
562
- property that contains the concrete errors.
563
- If all commands were queued successfully and an error is thrown by redis while
564
- processing the commands that error is going to be returned in the result array!
565
- No other command is going to be aborted though than the ones failing.
566
-
567
- You can either chain together `MULTI` commands as in the above example, or you
568
- can queue individual commands while still sending regular client command as in
569
- this example:
570
-
571
- ```js
572
- const redis = require("redis");
573
- const client = redis.createClient();
574
-
575
- // start a separate multi command queue
576
- const multi = client.multi();
577
-
578
- // add some commands to the queue
579
- multi.incr("count_cats", redis.print);
580
- multi.incr("count_dogs", redis.print);
581
-
582
- // runs a command immediately outside of the `multi` instance
583
- client.mset("count_cats", 100, "count_dogs", 50, redis.print);
584
-
585
- // drains the multi queue and runs each command atomically
586
- multi.exec(function(err, replies) {
587
- console.log(replies); // 101, 51
588
- });
589
- ```
590
-
591
- In addition to adding commands to the `MULTI` queue individually, you can also
592
- pass an array of commands and arguments to the constructor:
593
-
594
- ```js
595
- const redis = require("redis");
596
-
597
- const client = redis.createClient();
598
-
599
- client
600
- .multi([
601
- ["mget", "foo", "bar", redis.print],
602
- ["incr", "hello"],
603
- ])
604
- .exec(function(err, replies) {
605
- console.log(replies);
606
- });
607
- ```
608
-
609
- #### Multi.exec_atomic([callback])
610
-
611
- Identical to Multi.exec but with the difference that executing a single command
612
- will not use transactions.
613
-
614
- #### Optimistic Locks
615
-
616
- Using `multi` you can make sure your modifications run as a transaction, but you
617
- can't be sure you got there first. What if another client modified a key while
618
- you were working with it's data?
619
-
620
- To solve this, Redis supports the [WATCH](https://redis.io/topics/transactions)
621
- command, which is meant to be used with MULTI:
622
-
623
- ```js
624
- const redis = require("redis");
625
-
626
- const client = redis.createClient();
627
-
628
- client.watch("foo", function(watchError) {
629
- if (watchError) throw watchError;
630
-
631
- client.get("foo", function(getError, result) {
632
- if (getError) throw getError;
633
-
634
- // Process result
635
- // Heavy and time consuming operation here to generate "bar"
636
-
637
- client
638
- .multi()
639
- .set("foo", "bar")
640
- .exec(function(execError, results) {
641
- /**
642
- * If err is null, it means Redis successfully attempted
643
- * the operation.
644
- */
645
- if (execError) throw execError;
646
-
647
- /**
648
- * If results === null, it means that a concurrent client
649
- * changed the key while we were processing it and thus
650
- * the execution of the MULTI command was not performed.
651
- *
652
- * NOTICE: Failing an execution of MULTI is not considered
653
- * an error. So you will have err === null and results === null
654
- */
655
- });
656
- });
657
- });
658
- ```
659
-
660
- The above snippet shows the correct usage of `watch` with `multi`. Every time a
661
- watched key is changed before the execution of a `multi` command, the execution
662
- will return `null`. On a normal situation, the execution will return an array of
663
- values with the results of the operations.
664
-
665
- As stated in the snippet, failing the execution of a `multi` command being watched
666
- is not considered an error. The execution may return an error if, for example, the
667
- client cannot connect to Redis.
668
-
669
- An example where we can see the execution of a `multi` command fail is as follows:
670
-
671
- ```js
672
- const clients = {
673
- watcher: redis.createClient(),
674
- modifier: redis.createClient(),
675
- };
676
-
677
- clients.watcher.watch("foo", function(watchError) {
678
- if (watchError) throw watchError;
679
-
680
- // if you comment out the next line, the transaction will work
681
- clients.modifier.set("foo", Math.random(), setError => {
682
- if (setError) throw setError;
683
- });
684
-
685
- // using a setTimeout here to ensure that the MULTI/EXEC will come after the SET.
686
- // Normally, you would use a callback to ensure order, but I want the above SET command
687
- // to be easily comment-out-able.
688
- setTimeout(function() {
689
- clients.watcher
690
- .multi()
691
- .set("foo", "bar")
692
- .set("hello", "world")
693
- .exec((multiExecError, results) => {
694
- if (multiExecError) throw multiExecError;
695
-
696
- if (results === null) {
697
- console.log("transaction aborted because results were null");
698
- } else {
699
- console.log("transaction worked and returned", results);
700
- }
701
-
702
- clients.watcher.quit();
703
- clients.modifier.quit();
704
- });
705
- }, 1000);
706
- });
707
- ```
708
-
709
- #### `WATCH` limitations
710
-
711
- Redis WATCH works only on _whole_ key values. For example, with WATCH you can
712
- watch a hash for modifications, but you cannot watch a specific field of a hash.
713
-
714
- The following example would watch the keys `foo` and `hello`, not the field `hello`
715
- of hash `foo`:
716
-
717
- ```js
718
- const redis = require("redis");
719
-
720
- const client = redis.createClient();
721
-
722
- client.hget("foo", "hello", function(hashGetError, result) {
723
- if (hashGetError) throw hashGetError;
724
-
725
- //Do some processing with the value from this field and watch it after
726
-
727
- client.watch("foo", "hello", function(watchError) {
728
- if (watchError) throw watchError;
729
-
730
- /**
731
- * This is now watching the keys 'foo' and 'hello'. It is not
732
- * watching the field 'hello' of hash 'foo'. Because the key 'foo'
733
- * refers to a hash, this command is now watching the entire hash
734
- * for modifications.
735
- */
736
- });
737
- });
738
- ```
739
-
740
- This limitation also applies to sets (you can not watch individual set members)
741
- and any other collections.
742
-
743
- ### client.batch([commands])
744
-
745
- Identical to `.multi()` without transactions. This is recommended if you want to
746
- execute many commands at once but don't need to rely on transactions.
747
-
748
- `BATCH` commands are queued up until an `EXEC` is issued, and then all commands
749
- are run atomically by Redis. The interface returns an
750
- individual `Batch` object by calling `client.batch()`. The only difference
751
- between .batch and .multi is that no transaction is going to be used.
752
- Be aware that the errors are - just like in multi statements - in the result.
753
- Otherwise both, errors and results could be returned at the same time.
754
-
755
- If you fire many commands at once this is going to boost the execution speed
756
- significantly compared to firing the same commands in a loop without waiting for
757
- the result! See the benchmarks for further comparison. Please remember that all
758
- commands are kept in memory until they are fired.
759
-
760
- ### Monitor mode
761
-
762
- Redis supports the `MONITOR` command, which lets you see all commands received
763
- by the Redis server across all client connections, including from other client
764
- libraries and other computers.
765
-
766
- A `monitor` event is going to be emitted for every command fired from any client
767
- connected to the server including the monitoring client itself. The callback for
768
- the `monitor` event takes a timestamp from the Redis server, an array of command
769
- arguments and the raw monitoring string.
770
-
771
- #### Example:
772
-
773
- ```js
774
- const redis = require("redis");
775
- const client = redis.createClient();
776
-
777
- client.monitor(function(err, res) {
778
- console.log("Entering monitoring mode.");
779
- });
780
-
781
- client.set("foo", "bar");
782
-
783
- client.on("monitor", function(time, args, rawReply) {
784
- console.log(time + ": " + args); // 1458910076.446514:['set', 'foo', 'bar']
785
- });
786
- ```
787
-
788
- ## Extras
789
-
790
- Some other things you might find useful.
791
-
792
- ### `client.server_info`
793
-
794
- After the ready probe completes, the results from the INFO command are saved in
795
- the `client.server_info` object.
796
-
797
- The `versions` key contains an array of the elements of the version string for
798
- easy comparison.
799
-
800
- ```
801
- > client.server_info.redis_version
802
- '2.3.0'
803
- > client.server_info.versions
804
- [ 2, 3, 0 ]
805
- ```
806
-
807
- ### `redis.print()`
808
-
809
- A handy callback function for displaying return values when testing. Example:
810
-
811
- ```js
812
- const redis = require("redis");
813
- const client = redis.createClient();
814
-
815
- client.on("connect", function() {
816
- client.set("foo", "bar", redis.print); // => "Reply: OK"
817
- client.get("foo", redis.print); // => "Reply: bar"
818
- client.quit();
819
- });
820
- ```
821
-
822
- ### Multi-word commands
823
-
824
- To execute redis multi-word commands like `SCRIPT LOAD` or `CLIENT LIST` pass
825
- the second word as first parameter:
826
-
827
- ```js
828
- client.script("load", "return 1");
829
-
830
- client
831
- .multi()
832
- .script("load", "return 1")
833
- .exec();
834
-
835
- client.multi([["script", "load", "return 1"]]).exec();
836
- ```
837
-
838
- ### `client.duplicate([options][, callback])`
839
-
840
- Duplicate all current options and return a new redisClient instance. All options
841
- passed to the duplicate function are going to replace the original option. If
842
- you pass a callback, duplicate is going to wait until the client is ready and
843
- returns it in the callback. If an error occurs in the meanwhile, that is going
844
- to return an error instead in the callback.
845
-
846
- One example of when to use duplicate() would be to accommodate the connection-
847
- blocking redis commands `BRPOP`, `BLPOP`, and `BRPOPLPUSH`. If these commands
848
- are used on the same Redis client instance as non-blocking commands, the
849
- non-blocking ones may be queued up until after the blocking ones finish.
850
-
851
- Another reason to use duplicate() is when multiple DBs on the same server are
852
- accessed via the redis SELECT command. Each DB could use its own connection.
853
-
854
- ### `client.sendCommand(command_name[, [args][, callback]])`
855
-
856
- All Redis commands have been added to the `client` object. However, if new
857
- commands are introduced before this library is updated or if you want to add
858
- individual commands you can use `sendCommand()` to send arbitrary commands to
859
- Redis.
860
-
861
- All commands are sent as multi-bulk commands. `args` can either be an Array of
862
- arguments, or omitted / set to undefined.
863
-
864
- ### `redis.addCommand(command_name)`
865
-
866
- Calling addCommand will add a new command to the prototype. The exact command
867
- name will be used when calling using this new command. Using arbitrary arguments
868
- is possible as with any other command.
869
-
870
- ### `client.connected`
871
-
872
- Boolean tracking the state of the connection to the Redis server.
873
-
874
- ### `client.command_queue_length`
875
-
876
- The number of commands that have been sent to the Redis server but not yet
877
- replied to. You can use this to enforce some kind of maximum queue depth for
878
- commands while connected.
879
-
880
- ### `client.offline_queue_length`
881
-
882
- The number of commands that have been queued up for a future connection. You can
883
- use this to enforce some kind of maximum queue depth for pre-connection
884
- commands.
885
-
886
- ### Commands with Optional and Keyword arguments
887
-
888
- This applies to anything that uses an optional `[WITHSCORES]` or `[LIMIT offset count]` in the [redis.io/commands](http://redis.io/commands) documentation.
889
-
890
- #### Example
891
-
892
- ```js
893
- const args = ["myzset", 1, "one", 2, "two", 3, "three", 99, "ninety-nine"];
894
-
895
- client.zadd(args, function(addError, addResponse) {
896
- if (addError) throw addError;
897
- console.log("added " + addResponse + " items.");
898
-
899
- // -Infinity and +Infinity also work
900
- const args1 = ["myzset", "+inf", "-inf"];
901
- client.zrevrangebyscore(args1, function(rangeError, rangeResponse) {
902
- if (rangeError) throw rangeError;
903
- console.log("response1", rangeResponse);
904
- // ...
905
- });
906
-
907
- const max = 3;
908
- const min = 1;
909
- const offset = 1;
910
- const count = 2;
911
- const args2 = ["myzset", max, min, "WITHSCORES", "LIMIT", offset, count];
912
- client.zrevrangebyscore(args2, function(rangeError, rangeResponse) {
913
- if (rangeError) throw rangeError;
914
- console.log("response2", rangeResponse);
915
- // ...
916
- });
917
- });
918
- ```
919
-
920
- ## Performance
921
-
922
- Much effort has been spent to make Node Redis as fast as possible for common operations.
923
-
924
- ```
925
- Mac mini (2018), i7-3.2GHz and 32gb memory
926
- clients: 1, NodeJS: 12.15.0, Redis: 5.0.6, parser: javascript, connected by: tcp
927
- PING, 1/1 avg/max: 0.03/ 3.28 2501ms total, 31926 ops/sec
928
- PING, batch 50/1 avg/max: 0.08/ 3.35 2501ms total, 599460 ops/sec
929
- SET 4B str, 1/1 avg/max: 0.03/ 3.54 2501ms total, 29483 ops/sec
930
- SET 4B str, batch 50/1 avg/max: 0.10/ 1.39 2501ms total, 477689 ops/sec
931
- SET 4B buf, 1/1 avg/max: 0.04/ 1.52 2501ms total, 23449 ops/sec
932
- SET 4B buf, batch 50/1 avg/max: 0.20/ 2.09 2501ms total, 244382 ops/sec
933
- GET 4B str, 1/1 avg/max: 0.03/ 1.35 2501ms total, 32205 ops/sec
934
- GET 4B str, batch 50/1 avg/max: 0.09/ 2.02 2501ms total, 568992 ops/sec
935
- GET 4B buf, 1/1 avg/max: 0.03/ 2.93 2501ms total, 32802 ops/sec
936
- GET 4B buf, batch 50/1 avg/max: 0.08/ 1.03 2501ms total, 592863 ops/sec
937
- SET 4KiB str, 1/1 avg/max: 0.03/ 0.76 2501ms total, 29287 ops/sec
938
- SET 4KiB str, batch 50/1 avg/max: 0.35/ 2.97 2501ms total, 143163 ops/sec
939
- SET 4KiB buf, 1/1 avg/max: 0.04/ 1.21 2501ms total, 23070 ops/sec
940
- SET 4KiB buf, batch 50/1 avg/max: 0.28/ 2.34 2501ms total, 176809 ops/sec
941
- GET 4KiB str, 1/1 avg/max: 0.03/ 1.54 2501ms total, 29555 ops/sec
942
- GET 4KiB str, batch 50/1 avg/max: 0.18/ 1.59 2501ms total, 279188 ops/sec
943
- GET 4KiB buf, 1/1 avg/max: 0.03/ 1.80 2501ms total, 30681 ops/sec
944
- GET 4KiB buf, batch 50/1 avg/max: 0.17/ 5.00 2501ms total, 285886 ops/sec
945
- INCR, 1/1 avg/max: 0.03/ 1.99 2501ms total, 32757 ops/sec
946
- INCR, batch 50/1 avg/max: 0.09/ 2.54 2501ms total, 538964 ops/sec
947
- LPUSH, 1/1 avg/max: 0.05/ 4.85 2501ms total, 19482 ops/sec
948
- LPUSH, batch 50/1 avg/max: 0.12/ 9.52 2501ms total, 395562 ops/sec
949
- LRANGE 10, 1/1 avg/max: 0.06/ 9.21 2501ms total, 17062 ops/sec
950
- LRANGE 10, batch 50/1 avg/max: 0.22/ 1.03 2501ms total, 228269 ops/sec
951
- LRANGE 100, 1/1 avg/max: 0.05/ 1.44 2501ms total, 19051 ops/sec
952
- LRANGE 100, batch 50/1 avg/max: 0.99/ 3.46 2501ms total, 50480 ops/sec
953
- SET 4MiB str, 1/1 avg/max: 4.11/ 13.96 2501ms total, 243 ops/sec
954
- SET 4MiB str, batch 20/1 avg/max: 91.16/145.01 2553ms total, 219 ops/sec
955
- SET 4MiB buf, 1/1 avg/max: 2.81/ 11.90 2502ms total, 354 ops/sec
956
- SET 4MiB buf, batch 20/1 avg/max: 36.21/ 70.96 2535ms total, 552 ops/sec
957
- GET 4MiB str, 1/1 avg/max: 2.82/ 19.10 2503ms total, 354 ops/sec
958
- GET 4MiB str, batch 20/1 avg/max: 128.57/207.86 2572ms total, 156 ops/sec
959
- GET 4MiB buf, 1/1 avg/max: 3.13/ 23.88 2501ms total, 318 ops/sec
960
- GET 4MiB buf, batch 20/1 avg/max: 65.91/ 87.59 2572ms total, 303 ops/sec
961
- ```
962
-
963
- ## Debugging
964
-
965
- To get debug output run your Node Redis application with `NODE_DEBUG=redis`.
966
-
967
- This is also going to result in good stack traces opposed to useless ones
968
- otherwise for any async operation.
969
- If you only want to have good stack traces but not the debug output run your
970
- application in development mode instead (`NODE_ENV=development`).
971
-
972
- Good stack traces are only activated in development and debug mode as this
973
- results in a significant performance penalty.
974
-
975
- **_Comparison_**:
976
-
977
- Standard stack trace:
978
-
979
- ```
980
- ReplyError: ERR wrong number of arguments for 'set' command
981
- at parseError (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:158:12)
982
- at parseType (/home/ruben/repos/redis/node_modules/redis-parser/lib/parser.js:219:14)
983
- ```
984
-
985
- Debug stack trace:
986
-
987
- ```
988
- ReplyError: ERR wrong number of arguments for 'set' command
989
- at new Command (/home/ruben/repos/redis/lib/command.js:9:902)
990
- at RedisClient.set (/home/ruben/repos/redis/lib/commands.js:9:3238)
991
- at Context.<anonymous> (/home/ruben/repos/redis/test/good_stacks.spec.js:20:20)
992
- at callFnAsync (/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:349:8)
993
- at Test.Runnable.run (/home/ruben/repos/redis/node_modules/mocha/lib/runnable.js:301:7)
994
- at Runner.runTest (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:422:10)
995
- at /home/ruben/repos/redis/node_modules/mocha/lib/runner.js:528:12
996
- at next (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:342:14)
997
- at /home/ruben/repos/redis/node_modules/mocha/lib/runner.js:352:7
998
- at next (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:284:14)
999
- at Immediate._onImmediate (/home/ruben/repos/redis/node_modules/mocha/lib/runner.js:320:5)
1000
- at processImmediate [as _immediateCallback] (timers.js:383:17)
1001
- ```
1002
-
1003
- ## Contributing
1004
-
1005
- Please see the [contributing guide](CONTRIBUTING.md).
1006
-
1007
- ## License
1008
-
1009
- This repository is licensed under the "MIT" license. See [LICENSE](LICENSE).