1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-10 11:43:01 +03:00
* wip

* Worked on phrasing etc for v5 doc changes.

* Removed quite repetition of 'Rather'

* Update v4-to-v5.md

* Update v4-to-v5.md

* Update v4-to-v5.md

* WIP

* WIP

* clean SET command

* some more commands, multi.exec<'typed'>

* "typed" multi

* WIP

* upgrade deps

* wip

* wip

* fix #2469

* wip

* npm update

* wip

* wip

* wip

* wip

* some tests

* tests.yml

* wip

* wip

* merge master into v5

* some more commands

* some more commands

* WIP

* Release client@2.0.0-next.1

---------

Co-authored-by: Simon Prickett <simon@redislabs.com>
This commit is contained in:
Leibale Eidelman
2023-04-30 11:18:46 -04:00
committed by GitHub
parent 3273c8540d
commit b4bb68d8ab
540 changed files with 20282 additions and 17587 deletions

30
docs/RESP3.md Normal file
View File

@@ -0,0 +1,30 @@
# RESP3 => JS Type Mappings:
- Null (`_`) => `null`
- Boolean (`#`) => `boolean`
- Number (`:`) => `number | string`
- Big Number (`(`) => `BigInt | string`
- Double (`,`) => `number | string`
- Simple String (`+`) => `string | Buffer`
- Blob String (`$`) => `string | Buffer`
- Verbatim String (`=`) => `string | Buffer | VerbatimString` (TODO: `VerbatimString` typedoc link)
- Simple Error (`-`) => `ErrorReply`
- Blob Error (`!`) => `ErrorReply`
- Array (`*`) => `Array`
- Set (`~`) => `Array | Set`
- Map (`%`) => `object | Map | Array`
- Push (`>`) => `Array` => PubSub push/`'push'` event
> NOTE: the first type is the default type
## Map keys and Set members
When decoding Map to `Map | object` or Set to `Set`, keys/members of type "Simple String" or "Blob String" will be decoded as `string`s (ignoring flags) to allow lookup by type. If you need them as `Buffer`s, make sure to decode `Map`s/`Set`s as `Array`s.
## Not Implemented
These parts of RESP3 are not yet implemented in Redis itself (at the time of writing), so are not yet implemented in the Node-Redis client either:
- [Attribute type](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#attribute-type)
- [Streamed strings](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#streamed-strings)
- [Streamed aggregated data types](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md#streamed-aggregated-data-types)

View File

@@ -32,7 +32,7 @@ const value = await cluster.get('key');
| Property | Default | Description |
|------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| rootNodes | | An array of root nodes that are part of the cluster, which will be used to get the cluster topology. Each element in the array is a client configuration object. There is no need to specify every node in the cluster, 3 should be enough to reliably connect and obtain the cluster configuration from the server |
| rootNodes | | An array of root nodes that are part of the cluster, which will be used to get the cluster topology. Each element in the array is a client configuration object. There is no need to specify every node in the cluster: 3 should be enough to reliably connect and obtain the cluster configuration from the server |
| defaults | | The default configuration values for every client in the cluster. Use this for example when specifying an ACL user to connect with |
| useReplicas | `false` | When `true`, distribute load by executing readonly commands (such as `GET`, `GEOSEARCH`, etc.) across all cluster nodes. When `false`, only use master nodes |
| minimizeConnections | `false` | When `true`, `.connect()` will only discover the cluster topology, without actually connecting to all the nodes. Useful for short-term or Pub/Sub-only connections. |
@@ -105,9 +105,11 @@ createCluster({
## Command Routing
TODO request response policy
### Commands that operate on Redis Keys
Commands such as `GET`, `SET`, etc. are routed by the first key, for instance `MGET 1 2 3` will be routed by the key `1`.
Commands such as `GET`, `SET`, etc. are routed by the first key specified. For example `MGET 1 2 3` will be routed by the key `1`.
### [Server Commands](https://redis.io/commands#server)
@@ -115,4 +117,4 @@ Admin commands such as `MEMORY STATS`, `FLUSHALL`, etc. are not attached to the
### "Forwarded Commands"
Certain commands (e.g. `PUBLISH`) are forwarded to other cluster nodes by the Redis server. This client sends these commands to a random node in order to spread the load across the cluster.
Certain commands (e.g. `PUBLISH`) are forwarded to other cluster nodes by the Redis server. The client sends these commands to a random node in order to spread the load across the cluster.

14
docs/todo.md Normal file
View File

@@ -0,0 +1,14 @@
# Missing functionality
- `HEXISTS`: accepts one field only, should be the same as `EXISTS`
# Replies
`String` -> `Double`:
- `INCRBYFLOAT`
- `HINCRBYFLOAT`
- `GEODIST`
`Number` -> `Boolean`:
- `HSETNX` (deprecated)
- `SCRIPT EXISTS`

91
docs/v4-to-v5.md Normal file
View File

@@ -0,0 +1,91 @@
# v4 to v5 migration guide
## Command Options
In v4, command options are passed as a first optional argument:
```javascript
await client.get('key'); // `string | null`
await client.get(client.commandOptions({ returnBuffers: true }), 'key'); // `Buffer | null`
```
This has a couple of flaws:
1. The argument types are checked in runtime, which is a performance hit.
2. Code suggestions are less readable/usable, due to "function overloading".
3. Overall, "user code" is not as readable as it could be.
### The new API for v5
With the new API, instead of passing the options directly to the commands we use a "proxy client" to store them:
```javascript
await client.get('key'); // `string | null`
const proxyClient = client.withCommandOptions({
flags: {
[TYPES.BLOB_STRING]: Buffer
}
});
await proxyClient.get('key'); // `Buffer | null`
```
`withCommandOptions` can be used to override all of the command options, without reusing any existing ones.
To override just a specific option, use the following functions:
- `withFlags` - override `flags` only.
- `asap` - override `asap` to `true`.
- `isolated` - override `isolated` to `true`.
## Quit VS Disconnect
The `QUIT` command has been deprecated in Redis 7.2 and should now also be considered deprecated in Node-Redis. Instead of sending a `QUIT` command to the server, the client can simply close the network connection.
Rather than using `client.quit()`, your code should use `client.close()` or `client.disconnect()`.
TODO difference between `close` and `disconnect`...
## Scan Iterators
TODO
Yields chunks instead of individual items:
```javascript
for await (const chunk of client.scanIterator()) {
// `chunk` type is `Array<string>`
// will allow multi keys operations
await client.del(chunk);
}
```
## Commands
Some command arguments/replies have changed to align more closely to data types returned by Redis:
- `ACL GETUSER`: `selectors`
- `CLIENT KILL`: `enum ClientKillFilters` -> `const CLIENT_KILL_FILTERS` [^enum-to-constants]
- `CLUSTER FAILOVER`: `enum FailoverModes` -> `const FAILOVER_MODES` [^enum-to-constants]
- `LCS IDX`: `length` has been changed to `len`, `matches` has been changed from `Array<{ key1: RangeReply; key2: RangeReply; }>` to `Array<[key1: RangeReply, key2: RangeReply]>`
- `HEXISTS`: `boolean` -> `number` [^boolean-to-number]
- `HRANDFIELD_COUNT_WITHVALUES`: `Record<BlobString, BlobString>` -> `Array<{ field: BlobString; value: BlobString; }>` (it can return duplicates).
- `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`: cursor type is `string` instead of `number`?
- `HSETNX`: `boolean` -> `number` [^boolean-to-number]
- `ZINTER`: instead of `client.ZINTER('11, { WEIGHTS: [1] })` use `client.ZINTER({ key: '1', weight: 1 }])`
- `SETNX`: `boolean` -> `number` [^boolean-to-number]
- `COPY`: `destinationDb` -> `DB`, `replace` -> `REPLACE`, `boolean` -> `number` [^boolean-to-number]
- `EXPIRE`: `boolean` -> `number` [^boolean-to-number]
- `EXPIREAT`: `boolean` -> `number` [^boolean-to-number]
- `MOVE`: `boolean` -> `number` [^boolean-to-number]
- `PEXPIRE`: `boolean` -> `number` [^boolean-to-number]
- `PEXPIREAT`: `boolean` -> `number` [^boolean-to-number]
- `RENAMENX`: `boolean` -> `number` [^boolean-to-number]
- `HSCAN`: `tuples` has been renamed to `entries`
- `PFADD`: `boolean` -> `number` [^boolean-to-number]
- `SCRIPT EXISTS`: `Array<boolean>` -> `Array<number>` [^boolean-to-number]
- `SISMEMBER`: `boolean` -> `number` [^boolean-to-number]
- `SMISMEMBER`: `Array<boolean>` -> `Array<number>` [^boolean-to-number]
[^enum-to-constants]: TODO
[^boolean-to-number]: TODO

39
docs/v5.md Normal file
View File

@@ -0,0 +1,39 @@
# RESP3 Support
[RESP3](./RESP3.md)
```javascript
const client = createClient({
RESP: 3
});
client.on('error', err => console.error(err));
await client.connect();
client.hGetAll('key'); // Record<string, string>
client.withFlags({
[TYPES.MAP]: Map
}).hGetAll('key'); // Map<string, string>
client.withFlags({
[TYPES.MAP]: Map,
[TYPES.BLOB_STRING]: Buffer
}).hGetAll('key'); // Map<string, Buffer>
```
# `multi.exec<'typed'>` / `multi.execTyped`
We have introduced the ability to perform a "typed" `MULTI`/`EXEC` transaction. Rather than returning `Array<ReplyUnion>`, a transaction invoked with `.exec<'typed'>` will return types appropriate to the commands in the transaction where possible:
```javascript
const multi = client.multi().ping();
await multi.exec(); // Array<ReplyUnion>
await multi.exec<'typed'>(); // [string]
await multi.execTyped(); // [string]
```
# Request & Reply Policies
see [here](../docs/clustering.md#command-routing).