Skip to content

Commit f01f101

Browse files
Client Side Caching (#2947)
* CSC POC ontop of Parser * add csc file that weren't merged after patch * address review comments * nits to try and fix github * last change from review * Update client-side cache and improve documentation * Add client side caching RESP3 validation * Add documentation for RESP and unstableResp3 options * Add comprehensive cache statistics The `CacheStats` class provides detailed metrics like hit/miss counts, load success/failure counts, total load time, and eviction counts. It also offers derived metrics such as hit/miss rates, load failure rate, and average load penalty. The design is inspired by Caffeine. `BasicClientSideCache` now uses a `StatsCounter` to accumulate these statistics, exposed via a new `stats()` method. The previous `cacheHits()` and `cacheMisses()` methods have been removed. A `recordStats` option (default: true) in `ClientSideCacheConfig` allows disabling statistics collection. --------- Co-authored-by: Shaya Potter <[email protected]>
1 parent 6f961bd commit f01f101

25 files changed

+2330
-101
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,24 @@ of sending a `QUIT` command to the server, the client can simply close the netwo
235235
client.destroy();
236236
```
237237

238+
### Client Side Caching
239+
240+
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 Redis server will notify the client when cached results are no longer valid.
241+
242+
```typescript
243+
// Enable client side caching with RESP3
244+
const client = createClient({
245+
RESP: 3,
246+
clientSideCache: {
247+
ttl: 0, // Time-to-live (0 = no expiration)
248+
maxEntries: 0, // Maximum entries (0 = unlimited)
249+
evictPolicy: "LRU" // Eviction policy: "LRU" or "FIFO"
250+
}
251+
});
252+
```
253+
254+
See the [V5 documentation](./docs/v5.md#client-side-caching) for more details and advanced usage.
255+
238256
### Auto-Pipelining
239257

240258
Node Redis will automatically pipeline requests that are made during the same "tick".

docs/v5.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,100 @@ await multi.exec(); // Array<ReplyUnion>
8989
await multi.exec<'typed'>(); // [string]
9090
await multi.execTyped(); // [string]
9191
```
92+
93+
# Client Side Caching
94+
95+
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.
96+
97+
Client Side Caching is only supported with RESP3.
98+
99+
## Usage
100+
101+
There are two ways to implement client side caching:
102+
103+
### Anonymous Cache
104+
105+
```javascript
106+
const client = createClient({
107+
RESP: 3,
108+
clientSideCache: {
109+
ttl: 0, // Time-to-live in milliseconds (0 = no expiration)
110+
maxEntries: 0, // Maximum entries to store (0 = unlimited)
111+
evictPolicy: "LRU" // Eviction policy: "LRU" or "FIFO"
112+
}
113+
});
114+
```
115+
116+
In this instance, the cache is managed internally by the client.
117+
118+
### Controllable Cache
119+
120+
```javascript
121+
import { BasicClientSideCache } from 'redis';
122+
123+
const cache = new BasicClientSideCache({
124+
ttl: 0,
125+
maxEntries: 0,
126+
evictPolicy: "LRU"
127+
});
128+
129+
const client = createClient({
130+
RESP: 3,
131+
clientSideCache: cache
132+
});
133+
```
134+
135+
With this approach, you have direct access to the cache object for more control:
136+
137+
```javascript
138+
// Manually invalidate keys
139+
cache.invalidate(key);
140+
141+
// Clear the entire cache
142+
cache.clear();
143+
144+
// Get cache metrics
145+
// `cache.stats()` returns a `CacheStats` object with comprehensive statistics.
146+
const statistics = cache.stats();
147+
148+
// Key metrics:
149+
const hits = statistics.hitCount; // Number of cache hits
150+
const misses = statistics.missCount; // Number of cache misses
151+
const hitRate = statistics.hitRate(); // Cache hit rate (0.0 to 1.0)
152+
153+
// Many other metrics are available on the `statistics` object, e.g.:
154+
// statistics.missRate(), statistics.loadSuccessCount,
155+
// statistics.averageLoadPenalty(), statistics.requestCount()
156+
```
157+
158+
## Pooled Caching
159+
160+
Client side caching also works with client pools. For pooled clients, the cache is shared across all clients in the pool:
161+
162+
```javascript
163+
const client = createClientPool({RESP: 3}, {
164+
clientSideCache: {
165+
ttl: 0,
166+
maxEntries: 0,
167+
evictPolicy: "LRU"
168+
},
169+
minimum: 5
170+
});
171+
```
172+
173+
For a controllable pooled cache:
174+
175+
```javascript
176+
import { BasicPooledClientSideCache } from 'redis';
177+
178+
const cache = new BasicPooledClientSideCache({
179+
ttl: 0,
180+
maxEntries: 0,
181+
evictPolicy: "LRU"
182+
});
183+
184+
const client = createClientPool({RESP: 3}, {
185+
clientSideCache: cache,
186+
minimum: 5
187+
});
188+
```

packages/client/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ export { GEO_REPLY_WITH, GeoReplyWith } from './lib/commands/GEOSEARCH_WITH';
3434
export { SetOptions } from './lib/commands/SET';
3535

3636
export { REDIS_FLUSH_MODES } from './lib/commands/FLUSHALL';
37+
38+
export { BasicClientSideCache, BasicPooledClientSideCache } from './lib/client/cache';
39+

packages/client/lib/RESP/types.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,17 @@ export interface CommanderConfig<
314314
functions?: F;
315315
scripts?: S;
316316
/**
317-
* TODO
317+
* Specifies the Redis Serialization Protocol version to use.
318+
* RESP2 is the default (value 2), while RESP3 (value 3) provides
319+
* additional data types and features introduced in Redis 6.0.
318320
*/
319321
RESP?: RESP;
320322
/**
321-
* TODO
323+
* When set to true, enables commands that have unstable RESP3 implementations.
324+
* When using RESP3 protocol, commands marked as having unstable RESP3 support
325+
* will throw an error unless this flag is explicitly set to true.
326+
* This primarily affects modules like Redis Search where response formats
327+
* in RESP3 mode may change in future versions.
322328
*/
323329
unstableResp3?: boolean;
324330
}

0 commit comments

Comments
 (0)