@keyv/redis 5.1.1 → 5.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 (3) hide show
  1. package/dist/index.cjs +134 -41
  2. package/dist/index.js +134 -41
  3. package/package.json +7 -7
package/dist/index.cjs CHANGED
@@ -328,20 +328,50 @@ var KeyvRedis = class extends import_hookified.Hookified {
328
328
  * @param {KeyvEntry[]} entries - the key value pairs to set with optional ttl
329
329
  */
330
330
  async setMany(entries) {
331
- const client = await this.getClient();
332
331
  try {
333
- const multi = client.multi();
334
- for (const { key, value, ttl } of entries) {
335
- const prefixedKey = this.createKeyPrefix(key, this._namespace);
336
- if (ttl) {
337
- multi.set(prefixedKey, value, { PX: ttl });
338
- } else {
339
- multi.set(prefixedKey, value);
332
+ if (this.isCluster()) {
333
+ await this.getClient();
334
+ const slotMap = /* @__PURE__ */ new Map();
335
+ for (const entry of entries) {
336
+ const prefixedKey = this.createKeyPrefix(entry.key, this._namespace);
337
+ const slot = (0, import_cluster_key_slot.default)(prefixedKey);
338
+ const slotEntries = slotMap.get(slot) ?? [];
339
+ slotEntries.push(entry);
340
+ slotMap.set(slot, slotEntries);
341
+ }
342
+ await Promise.all(
343
+ Array.from(slotMap.entries(), async ([slot, slotEntries]) => {
344
+ const client = await this.getSlotMaster(slot);
345
+ const multi = client.multi();
346
+ for (const { key, value, ttl } of slotEntries) {
347
+ const prefixedKey = this.createKeyPrefix(key, this._namespace);
348
+ if (ttl) {
349
+ multi.set(prefixedKey, value, { PX: ttl });
350
+ } else {
351
+ multi.set(prefixedKey, value);
352
+ }
353
+ }
354
+ await multi.exec();
355
+ })
356
+ );
357
+ } else {
358
+ const client = await this.getClient();
359
+ const multi = client.multi();
360
+ for (const { key, value, ttl } of entries) {
361
+ const prefixedKey = this.createKeyPrefix(key, this._namespace);
362
+ if (ttl) {
363
+ multi.set(prefixedKey, value, { PX: ttl });
364
+ } else {
365
+ multi.set(prefixedKey, value);
366
+ }
340
367
  }
368
+ await multi.exec();
341
369
  }
342
- await multi.exec();
343
370
  } catch (error) {
344
371
  this.emit("error", error);
372
+ if (this._throwOnConnectError && error.message === "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true." /* RedisClientNotConnectedThrown */) {
373
+ throw error;
374
+ }
345
375
  if (this._throwOnErrors) {
346
376
  throw error;
347
377
  }
@@ -372,19 +402,46 @@ var KeyvRedis = class extends import_hookified.Hookified {
372
402
  * @returns {Promise<Array<boolean>>} - array of booleans for each key if it exists
373
403
  */
374
404
  async hasMany(keys) {
375
- const client = await this.getClient();
376
405
  try {
377
- const multi = client.multi();
378
- for (const key of keys) {
379
- const prefixedKey = this.createKeyPrefix(key, this._namespace);
380
- multi.exists(prefixedKey);
381
- }
382
- const results = await multi.exec();
383
- return results.map(
384
- (result) => typeof result === "number" && result === 1
406
+ const prefixedKeys = keys.map(
407
+ (key) => this.createKeyPrefix(key, this._namespace)
385
408
  );
409
+ if (this.isCluster()) {
410
+ const slotMap = this.getSlotMap(prefixedKeys);
411
+ const resultMap = /* @__PURE__ */ new Map();
412
+ await Promise.all(
413
+ Array.from(slotMap.entries(), async ([slot, slotKeys]) => {
414
+ const client = await this.getSlotMaster(slot);
415
+ const multi = client.multi();
416
+ for (const key of slotKeys) {
417
+ multi.exists(key);
418
+ }
419
+ const results = await multi.exec();
420
+ for (const [index, result] of results.entries()) {
421
+ resultMap.set(
422
+ slotKeys[index],
423
+ typeof result === "number" && result === 1
424
+ );
425
+ }
426
+ })
427
+ );
428
+ return prefixedKeys.map((key) => resultMap.get(key) ?? false);
429
+ } else {
430
+ const client = await this.getClient();
431
+ const multi = client.multi();
432
+ for (const key of prefixedKeys) {
433
+ multi.exists(key);
434
+ }
435
+ const results = await multi.exec();
436
+ return results.map(
437
+ (result) => typeof result === "number" && result === 1
438
+ );
439
+ }
386
440
  } catch (error) {
387
441
  this.emit("error", error);
442
+ if (this._throwOnConnectError && error.message === "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true." /* RedisClientNotConnectedThrown */) {
443
+ throw error;
444
+ }
388
445
  if (this._throwOnErrors) {
389
446
  throw error;
390
447
  }
@@ -461,25 +518,53 @@ var KeyvRedis = class extends import_hookified.Hookified {
461
518
  */
462
519
  async deleteMany(keys) {
463
520
  let result = false;
464
- const client = await this.getClient();
465
521
  try {
466
- const multi = client.multi();
467
- for (const key of keys) {
468
- const prefixedKey = this.createKeyPrefix(key, this._namespace);
469
- if (this._useUnlink) {
470
- multi.unlink(prefixedKey);
471
- } else {
472
- multi.del(prefixedKey);
522
+ const prefixedKeys = keys.map(
523
+ (key) => this.createKeyPrefix(key, this._namespace)
524
+ );
525
+ if (this.isCluster()) {
526
+ const slotMap = this.getSlotMap(prefixedKeys);
527
+ await Promise.all(
528
+ Array.from(slotMap.entries(), async ([slot, slotKeys]) => {
529
+ const client = await this.getSlotMaster(slot);
530
+ const multi = client.multi();
531
+ for (const key of slotKeys) {
532
+ if (this._useUnlink) {
533
+ multi.unlink(key);
534
+ } else {
535
+ multi.del(key);
536
+ }
537
+ }
538
+ const results = await multi.exec();
539
+ for (const deleted of results) {
540
+ if (typeof deleted === "number" && deleted > 0) {
541
+ result = true;
542
+ }
543
+ }
544
+ })
545
+ );
546
+ } else {
547
+ const client = await this.getClient();
548
+ const multi = client.multi();
549
+ for (const key of prefixedKeys) {
550
+ if (this._useUnlink) {
551
+ multi.unlink(key);
552
+ } else {
553
+ multi.del(key);
554
+ }
473
555
  }
474
- }
475
- const results = await multi.exec();
476
- for (const deleted of results) {
477
- if (typeof deleted === "number" && deleted > 0) {
478
- result = true;
556
+ const results = await multi.exec();
557
+ for (const deleted of results) {
558
+ if (typeof deleted === "number" && deleted > 0) {
559
+ result = true;
560
+ }
479
561
  }
480
562
  }
481
563
  } catch (error) {
482
564
  this.emit("error", error);
565
+ if (this._throwOnConnectError && error.message === "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true." /* RedisClientNotConnectedThrown */) {
566
+ throw error;
567
+ }
483
568
  if (this._throwOnErrors) {
484
569
  throw error;
485
570
  }
@@ -631,17 +716,25 @@ var KeyvRedis = class extends import_hookified.Hookified {
631
716
  * by separating the keys by slot to solve the CROSS-SLOT restriction.
632
717
  */
633
718
  async mget(keys) {
634
- const slotMap = this.getSlotMap(keys);
635
719
  const valueMap = /* @__PURE__ */ new Map();
636
- await Promise.all(
637
- Array.from(slotMap.entries(), async ([slot, keys2]) => {
638
- const client = await this.getSlotMaster(slot);
639
- const values = await client.mGet(keys2);
640
- for (const [index, value] of values.entries()) {
641
- valueMap.set(keys2[index], value ?? void 0);
642
- }
643
- })
644
- );
720
+ if (this.isCluster()) {
721
+ const slotMap = this.getSlotMap(keys);
722
+ await Promise.all(
723
+ Array.from(slotMap.entries(), async ([slot, slotKeys]) => {
724
+ const client = await this.getSlotMaster(slot);
725
+ const values = await client.mGet(slotKeys);
726
+ for (const [index, value] of values.entries()) {
727
+ valueMap.set(slotKeys[index], value ?? void 0);
728
+ }
729
+ })
730
+ );
731
+ } else {
732
+ const client = await this.getClient();
733
+ const values = await client.mGet(keys);
734
+ for (const [index, value] of values.entries()) {
735
+ valueMap.set(keys[index], value ?? void 0);
736
+ }
737
+ }
645
738
  return keys.map((key) => valueMap.get(key));
646
739
  }
647
740
  /**
package/dist/index.js CHANGED
@@ -294,20 +294,50 @@ var KeyvRedis = class extends Hookified {
294
294
  * @param {KeyvEntry[]} entries - the key value pairs to set with optional ttl
295
295
  */
296
296
  async setMany(entries) {
297
- const client = await this.getClient();
298
297
  try {
299
- const multi = client.multi();
300
- for (const { key, value, ttl } of entries) {
301
- const prefixedKey = this.createKeyPrefix(key, this._namespace);
302
- if (ttl) {
303
- multi.set(prefixedKey, value, { PX: ttl });
304
- } else {
305
- multi.set(prefixedKey, value);
298
+ if (this.isCluster()) {
299
+ await this.getClient();
300
+ const slotMap = /* @__PURE__ */ new Map();
301
+ for (const entry of entries) {
302
+ const prefixedKey = this.createKeyPrefix(entry.key, this._namespace);
303
+ const slot = calculateSlot(prefixedKey);
304
+ const slotEntries = slotMap.get(slot) ?? [];
305
+ slotEntries.push(entry);
306
+ slotMap.set(slot, slotEntries);
307
+ }
308
+ await Promise.all(
309
+ Array.from(slotMap.entries(), async ([slot, slotEntries]) => {
310
+ const client = await this.getSlotMaster(slot);
311
+ const multi = client.multi();
312
+ for (const { key, value, ttl } of slotEntries) {
313
+ const prefixedKey = this.createKeyPrefix(key, this._namespace);
314
+ if (ttl) {
315
+ multi.set(prefixedKey, value, { PX: ttl });
316
+ } else {
317
+ multi.set(prefixedKey, value);
318
+ }
319
+ }
320
+ await multi.exec();
321
+ })
322
+ );
323
+ } else {
324
+ const client = await this.getClient();
325
+ const multi = client.multi();
326
+ for (const { key, value, ttl } of entries) {
327
+ const prefixedKey = this.createKeyPrefix(key, this._namespace);
328
+ if (ttl) {
329
+ multi.set(prefixedKey, value, { PX: ttl });
330
+ } else {
331
+ multi.set(prefixedKey, value);
332
+ }
306
333
  }
334
+ await multi.exec();
307
335
  }
308
- await multi.exec();
309
336
  } catch (error) {
310
337
  this.emit("error", error);
338
+ if (this._throwOnConnectError && error.message === "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true." /* RedisClientNotConnectedThrown */) {
339
+ throw error;
340
+ }
311
341
  if (this._throwOnErrors) {
312
342
  throw error;
313
343
  }
@@ -338,19 +368,46 @@ var KeyvRedis = class extends Hookified {
338
368
  * @returns {Promise<Array<boolean>>} - array of booleans for each key if it exists
339
369
  */
340
370
  async hasMany(keys) {
341
- const client = await this.getClient();
342
371
  try {
343
- const multi = client.multi();
344
- for (const key of keys) {
345
- const prefixedKey = this.createKeyPrefix(key, this._namespace);
346
- multi.exists(prefixedKey);
347
- }
348
- const results = await multi.exec();
349
- return results.map(
350
- (result) => typeof result === "number" && result === 1
372
+ const prefixedKeys = keys.map(
373
+ (key) => this.createKeyPrefix(key, this._namespace)
351
374
  );
375
+ if (this.isCluster()) {
376
+ const slotMap = this.getSlotMap(prefixedKeys);
377
+ const resultMap = /* @__PURE__ */ new Map();
378
+ await Promise.all(
379
+ Array.from(slotMap.entries(), async ([slot, slotKeys]) => {
380
+ const client = await this.getSlotMaster(slot);
381
+ const multi = client.multi();
382
+ for (const key of slotKeys) {
383
+ multi.exists(key);
384
+ }
385
+ const results = await multi.exec();
386
+ for (const [index, result] of results.entries()) {
387
+ resultMap.set(
388
+ slotKeys[index],
389
+ typeof result === "number" && result === 1
390
+ );
391
+ }
392
+ })
393
+ );
394
+ return prefixedKeys.map((key) => resultMap.get(key) ?? false);
395
+ } else {
396
+ const client = await this.getClient();
397
+ const multi = client.multi();
398
+ for (const key of prefixedKeys) {
399
+ multi.exists(key);
400
+ }
401
+ const results = await multi.exec();
402
+ return results.map(
403
+ (result) => typeof result === "number" && result === 1
404
+ );
405
+ }
352
406
  } catch (error) {
353
407
  this.emit("error", error);
408
+ if (this._throwOnConnectError && error.message === "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true." /* RedisClientNotConnectedThrown */) {
409
+ throw error;
410
+ }
354
411
  if (this._throwOnErrors) {
355
412
  throw error;
356
413
  }
@@ -427,25 +484,53 @@ var KeyvRedis = class extends Hookified {
427
484
  */
428
485
  async deleteMany(keys) {
429
486
  let result = false;
430
- const client = await this.getClient();
431
487
  try {
432
- const multi = client.multi();
433
- for (const key of keys) {
434
- const prefixedKey = this.createKeyPrefix(key, this._namespace);
435
- if (this._useUnlink) {
436
- multi.unlink(prefixedKey);
437
- } else {
438
- multi.del(prefixedKey);
488
+ const prefixedKeys = keys.map(
489
+ (key) => this.createKeyPrefix(key, this._namespace)
490
+ );
491
+ if (this.isCluster()) {
492
+ const slotMap = this.getSlotMap(prefixedKeys);
493
+ await Promise.all(
494
+ Array.from(slotMap.entries(), async ([slot, slotKeys]) => {
495
+ const client = await this.getSlotMaster(slot);
496
+ const multi = client.multi();
497
+ for (const key of slotKeys) {
498
+ if (this._useUnlink) {
499
+ multi.unlink(key);
500
+ } else {
501
+ multi.del(key);
502
+ }
503
+ }
504
+ const results = await multi.exec();
505
+ for (const deleted of results) {
506
+ if (typeof deleted === "number" && deleted > 0) {
507
+ result = true;
508
+ }
509
+ }
510
+ })
511
+ );
512
+ } else {
513
+ const client = await this.getClient();
514
+ const multi = client.multi();
515
+ for (const key of prefixedKeys) {
516
+ if (this._useUnlink) {
517
+ multi.unlink(key);
518
+ } else {
519
+ multi.del(key);
520
+ }
439
521
  }
440
- }
441
- const results = await multi.exec();
442
- for (const deleted of results) {
443
- if (typeof deleted === "number" && deleted > 0) {
444
- result = true;
522
+ const results = await multi.exec();
523
+ for (const deleted of results) {
524
+ if (typeof deleted === "number" && deleted > 0) {
525
+ result = true;
526
+ }
445
527
  }
446
528
  }
447
529
  } catch (error) {
448
530
  this.emit("error", error);
531
+ if (this._throwOnConnectError && error.message === "Redis client is not connected or has failed to connect. This is thrown because throwOnConnectError is set to true." /* RedisClientNotConnectedThrown */) {
532
+ throw error;
533
+ }
449
534
  if (this._throwOnErrors) {
450
535
  throw error;
451
536
  }
@@ -597,17 +682,25 @@ var KeyvRedis = class extends Hookified {
597
682
  * by separating the keys by slot to solve the CROSS-SLOT restriction.
598
683
  */
599
684
  async mget(keys) {
600
- const slotMap = this.getSlotMap(keys);
601
685
  const valueMap = /* @__PURE__ */ new Map();
602
- await Promise.all(
603
- Array.from(slotMap.entries(), async ([slot, keys2]) => {
604
- const client = await this.getSlotMaster(slot);
605
- const values = await client.mGet(keys2);
606
- for (const [index, value] of values.entries()) {
607
- valueMap.set(keys2[index], value ?? void 0);
608
- }
609
- })
610
- );
686
+ if (this.isCluster()) {
687
+ const slotMap = this.getSlotMap(keys);
688
+ await Promise.all(
689
+ Array.from(slotMap.entries(), async ([slot, slotKeys]) => {
690
+ const client = await this.getSlotMaster(slot);
691
+ const values = await client.mGet(slotKeys);
692
+ for (const [index, value] of values.entries()) {
693
+ valueMap.set(slotKeys[index], value ?? void 0);
694
+ }
695
+ })
696
+ );
697
+ } else {
698
+ const client = await this.getClient();
699
+ const values = await client.mGet(keys);
700
+ for (const [index, value] of values.entries()) {
701
+ valueMap.set(keys[index], value ?? void 0);
702
+ }
703
+ }
611
704
  return keys.map((key) => valueMap.get(key));
612
705
  }
613
706
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keyv/redis",
3
- "version": "5.1.1",
3
+ "version": "5.1.2",
4
4
  "description": "Redis storage adapter for Keyv",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -34,20 +34,20 @@
34
34
  },
35
35
  "homepage": "https://github.com/jaredwray/keyv",
36
36
  "dependencies": {
37
- "@redis/client": "^5.7.0",
37
+ "@redis/client": "^5.8.2",
38
38
  "cluster-key-slot": "^1.1.2",
39
- "hookified": "^1.11.0"
39
+ "hookified": "^1.12.0"
40
40
  },
41
41
  "peerDependencies": {
42
- "keyv": "^5.5.0"
42
+ "keyv": "^5.5.1"
43
43
  },
44
44
  "devDependencies": {
45
- "@biomejs/biome": "^2.2.0",
46
- "@faker-js/faker": "^9.9.0",
45
+ "@biomejs/biome": "^2.2.3",
46
+ "@faker-js/faker": "^10.0.0",
47
47
  "@vitest/coverage-v8": "^3.2.4",
48
48
  "rimraf": "^6.0.1",
49
49
  "timekeeper": "^2.3.1",
50
- "tsd": "^0.32.0",
50
+ "tsd": "^0.33.0",
51
51
  "vitest": "^3.2.4",
52
52
  "@keyv/test-suite": "^2.1.1"
53
53
  },