# RESP3 Support

Node Redis v5 adds support for [RESP3](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md), the new Redis serialization protocol. RESP3 offers richer data types and improved type handling compared to RESP2.

To use RESP3, specify it when creating your client:

```javascript
import { createClient } from 'redis';

const client = createClient({
  RESP: 3
});
```

## Type Mapping

With RESP3, you can leverage the protocol's richer type system. You can customize how different Redis types are represented in JavaScript using type mapping:

```javascript
import { createClient, RESP_TYPES } from 'redis';

// By default
await client.hGetAll('key'); // Record<string, string>

// Use Map instead of plain object
await client.withTypeMapping({
  [RESP_TYPES.MAP]: Map
}).hGetAll('key'); // Map<string, string>

// Use both Map and Buffer
await client.withTypeMapping({
  [RESP_TYPES.MAP]: Map,
  [RESP_TYPES.BLOB_STRING]: Buffer
}).hGetAll('key'); // Map<string, Buffer>
```

This replaces the previous approach of using `commandOptions({ returnBuffers: true })` in v4.

## PubSub in RESP3

RESP3 uses a different mechanism for handling Pub/Sub messages. Instead of modifying the `onReply` handler as in RESP2, RESP3 provides a dedicated `onPush` handler. When using RESP3, the client automatically uses this more efficient push notification system.

## Known Limitations

### Unstable Commands

Some Redis commands have unstable RESP3 transformations. These commands will throw an error when used with RESP3 unless you explicitly opt in to using them by setting `unstableResp3: true` in your client configuration:

```javascript
const client = createClient({
  RESP: 3,
  unstableResp3: true
});
```

The following commands have unstable RESP3 implementations:

1. **Stream Commands**:
   - `XREAD` and `XREADGROUP` - The response format differs between RESP2 and RESP3

2. **Search Commands (RediSearch)**:
   - `FT.AGGREGATE`
   - `FT.AGGREGATE_WITHCURSOR`
   - `FT.CURSOR_READ`
   - `FT.INFO`
   - `FT.PROFILE_AGGREGATE`
   - `FT.PROFILE_SEARCH`
   - `FT.SEARCH`
   - `FT.SEARCH_NOCONTENT`
   - `FT.SPELLCHECK`

3. **Time Series Commands**:
   - `TS.INFO`
   - `TS.INFO_DEBUG`

If you need to use these commands with RESP3, be aware that the response format might change in future versions.

# Sentinel Support

[Sentinel](./sentinel.md)

# `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]
```

# Client Side Caching

Node Redis v5 adds support for [Client Side Caching](https://redis.io/docs/manual/client-side-caching/), which enables clients to cache query results locally. The server will notify the client when cached results are no longer valid.

Client Side Caching is only supported with RESP3.

## Usage

There are two ways to implement client side caching:

### Anonymous Cache

```javascript
const client = createClient({
  RESP: 3,
  clientSideCache: {
    ttl: 0,             // Time-to-live in milliseconds (0 = no expiration)
    maxEntries: 0,      // Maximum entries to store (0 = unlimited)
    evictPolicy: "LRU"  // Eviction policy: "LRU" or "FIFO"
  }
});
```

In this instance, the cache is managed internally by the client.

### Controllable Cache

```javascript
import { BasicClientSideCache } from 'redis';

const cache = new BasicClientSideCache({
  ttl: 0,
  maxEntries: 0,
  evictPolicy: "LRU"
});

const client = createClient({
  RESP: 3,
  clientSideCache: cache
});
```

With this approach, you have direct access to the cache object for more control:

```javascript
// Manually invalidate keys
cache.invalidate(key);

// Clear the entire cache
cache.clear();

// Get cache metrics
// `cache.stats()` returns a `CacheStats` object with comprehensive statistics.
const statistics = cache.stats();

// Key metrics:
const hits = statistics.hitCount;        // Number of cache hits
const misses = statistics.missCount;      // Number of cache misses
const hitRate = statistics.hitRate();     // Cache hit rate (0.0 to 1.0)

// Many other metrics are available on the `statistics` object, e.g.:
// statistics.missRate(), statistics.loadSuccessCount,
// statistics.averageLoadPenalty(), statistics.requestCount()
```

## Pooled Caching

Client side caching also works with client pools. For pooled clients, the cache is shared across all clients in the pool:

```javascript
const client = createClientPool({RESP: 3}, {
  clientSideCache: {
    ttl: 0,
    maxEntries: 0,
    evictPolicy: "LRU"
  },
  minimum: 5
});
```

For a controllable pooled cache:

```javascript
import { BasicPooledClientSideCache } from 'redis';

const cache = new BasicPooledClientSideCache({
  ttl: 0,
  maxEntries: 0,
  evictPolicy: "LRU"
});

const client = createClientPool({RESP: 3}, {
  clientSideCache: cache,
  minimum: 5
});
```
