Skip to content

Commit e5d0f03

Browse files
authored
valkey - feat: adding in getMany, setMany, deleteMany, etc (#1877)
* valkey - feat: adding in getMany, setMany, deleteMany, etc * adding coverage * updating tests * adding cluster tests * private method changes and clustering readme * migrating to faker-js/faker * Update index.ts * adding in jsDoc
1 parent 4f4cfa7 commit e5d0f03

6 files changed

Lines changed: 819 additions & 117 deletions

File tree

pnpm-lock.yaml

Lines changed: 12 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

storage/valkey/README.md

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ We are using the [iovalkey](https://www.npmjs.com/package/iovalkey) which is a N
2828
- [.get(key)](#getkey)
2929
- [.getMany(keys)](#getmanykeys)
3030
- [.set(key, value, ttl?)](#setkey-value-ttl)
31+
- [.setMany(entries)](#setmanyentries)
3132
- [.delete(key)](#deletekey)
3233
- [.deleteMany(keys)](#deletemanykeys)
33-
- [.clear()](#clear)
3434
- [.has(key)](#haskey)
35+
- [.hasMany(keys)](#hasmanykeys)
36+
- [.clear()](#clear)
3537
- [.iterator(namespace?)](#iteratornamespace)
3638
- [.disconnect()](#disconnect)
39+
- [Clustering](#clustering)
3740
- [License](#license)
3841

3942
# Install
@@ -221,6 +224,17 @@ await store.set('foo', 'bar');
221224
await store.set('foo', 'bar', 5000); // expires in 5 seconds
222225
```
223226

227+
### .setMany(entries)
228+
229+
Sets multiple key-value pairs in a single batch operation. Each entry can have an optional TTL in milliseconds. Entries with `undefined` values are skipped.
230+
231+
```js
232+
await store.setMany([
233+
{ key: 'foo', value: 'bar' },
234+
{ key: 'baz', value: 'qux', ttl: 5000 },
235+
]);
236+
```
237+
224238
### .delete(key)
225239

226240
Deletes a key-value pair from the store. Returns `true` if the key existed and was deleted, `false` otherwise.
@@ -231,26 +245,35 @@ const deleted = await store.delete('foo');
231245

232246
### .deleteMany(keys)
233247

234-
Deletes multiple key-value pairs from the store. Returns `true` if all keys were deleted successfully.
248+
Deletes multiple key-value pairs from the store in a single batch operation. Returns `true` if at least one key was deleted, `false` otherwise.
235249

236250
```js
237251
const deleted = await store.deleteMany(['foo', 'bar']);
238252
```
239253

240-
### .clear()
254+
### .has(key)
241255

242-
Clears all entries from the store. If a namespace is set, only entries within that namespace are cleared.
256+
Returns `true` if the key exists in the store, `false` otherwise.
243257

244258
```js
245-
await store.clear();
259+
const exists = await store.has('foo');
246260
```
247261

248-
### .has(key)
262+
### .hasMany(keys)
249263

250-
Returns `true` if the key exists in the store, `false` otherwise.
264+
Checks if multiple keys exist in the store in a single batch operation. Returns an array of booleans.
251265

252266
```js
253-
const exists = await store.has('foo');
267+
const results = await store.hasMany(['foo', 'bar', 'baz']);
268+
// [true, true, false]
269+
```
270+
271+
### .clear()
272+
273+
Clears all entries from the store. If a namespace is set, only entries within that namespace are cleared.
274+
275+
```js
276+
await store.clear();
254277
```
255278

256279
### .iterator(namespace?)
@@ -271,6 +294,31 @@ Disconnects from the Valkey server.
271294
await store.disconnect();
272295
```
273296

297+
## Clustering
298+
299+
The adapter supports Valkey and Redis clusters via iovalkey's `Cluster` class. Pass a `Redis.Cluster` instance directly to the constructor:
300+
301+
```js
302+
import KeyvValkey from '@keyv/valkey';
303+
import Redis from 'iovalkey';
304+
305+
const cluster = new Redis.Cluster([
306+
{ host: '127.0.0.1', port: 7001 },
307+
{ host: '127.0.0.1', port: 7002 },
308+
{ host: '127.0.0.1', port: 7003 },
309+
]);
310+
const store = new KeyvValkey(cluster);
311+
```
312+
313+
Batch methods (`getMany`, `setMany`, `deleteMany`, `hasMany`) automatically group keys by hash slot and run separate transactions per slot group. This avoids `CROSSSLOT` errors without any extra configuration.
314+
315+
Single-key methods (`get`, `set`, `delete`, `has`) work automatically in cluster mode — iovalkey routes each command to the correct node.
316+
317+
### Cluster gotchas
318+
319+
- **`clear()` with `useSets: false` (the default)** uses the `KEYS` command, which only scans the node that receives the command. In cluster mode this may miss keys on other nodes. Set `useSets: true` if you need reliable `clear()` across all cluster nodes.
320+
- **`iterator()` in cluster mode** uses `SCAN`, which only iterates keys on the node the command is routed to. It may not return all keys across the cluster.
321+
274322
## License
275323

276324
[MIT © Jared Wray](LISCENCE)

storage/valkey/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,12 @@
5353
},
5454
"homepage": "https://github.com/jaredwray/keyv",
5555
"dependencies": {
56+
"cluster-key-slot": "^1.1.0",
5657
"iovalkey": "^0.3.3"
5758
},
5859
"devDependencies": {
5960
"@biomejs/biome": "^2.3.8",
61+
"@faker-js/faker": "^10.2.0",
6062
"@keyv/test-suite": "workspace:^",
6163
"@vitest/coverage-v8": "^4.0.15",
6264
"keyv": "workspace:^",

0 commit comments

Comments
 (0)