redis 4.3.1 → 5.4.1

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +190 -0
  3. data/README.md +132 -154
  4. data/lib/redis/client.rb +81 -600
  5. data/lib/redis/commands/bitmaps.rb +73 -0
  6. data/lib/redis/commands/cluster.rb +28 -0
  7. data/lib/redis/commands/connection.rb +53 -0
  8. data/lib/redis/commands/geo.rb +84 -0
  9. data/lib/redis/commands/hashes.rb +258 -0
  10. data/lib/redis/commands/hyper_log_log.rb +37 -0
  11. data/lib/redis/commands/keys.rb +459 -0
  12. data/lib/redis/commands/lists.rb +339 -0
  13. data/lib/redis/commands/pubsub.rb +81 -0
  14. data/lib/redis/commands/scripting.rb +114 -0
  15. data/lib/redis/commands/server.rb +188 -0
  16. data/lib/redis/commands/sets.rb +218 -0
  17. data/lib/redis/commands/sorted_sets.rb +922 -0
  18. data/lib/redis/commands/streams.rb +409 -0
  19. data/lib/redis/commands/strings.rb +314 -0
  20. data/lib/redis/commands/transactions.rb +115 -0
  21. data/lib/redis/commands.rb +239 -0
  22. data/lib/redis/distributed.rb +236 -77
  23. data/lib/redis/errors.rb +20 -41
  24. data/lib/redis/hash_ring.rb +26 -26
  25. data/lib/redis/pipeline.rb +70 -120
  26. data/lib/redis/subscribe.rb +50 -14
  27. data/lib/redis/version.rb +1 -1
  28. data/lib/redis.rb +104 -3465
  29. metadata +27 -57
  30. data/lib/redis/cluster/command.rb +0 -81
  31. data/lib/redis/cluster/command_loader.rb +0 -34
  32. data/lib/redis/cluster/key_slot_converter.rb +0 -72
  33. data/lib/redis/cluster/node.rb +0 -107
  34. data/lib/redis/cluster/node_key.rb +0 -31
  35. data/lib/redis/cluster/node_loader.rb +0 -37
  36. data/lib/redis/cluster/option.rb +0 -93
  37. data/lib/redis/cluster/slot.rb +0 -86
  38. data/lib/redis/cluster/slot_loader.rb +0 -49
  39. data/lib/redis/cluster.rb +0 -295
  40. data/lib/redis/connection/command_helper.rb +0 -39
  41. data/lib/redis/connection/hiredis.rb +0 -67
  42. data/lib/redis/connection/registry.rb +0 -13
  43. data/lib/redis/connection/ruby.rb +0 -427
  44. data/lib/redis/connection/synchrony.rb +0 -146
  45. data/lib/redis/connection.rb +0 -11
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "hash_ring"
3
+ require "redis/hash_ring"
4
4
 
5
5
  class Redis
6
6
  class Distributed
@@ -20,7 +20,7 @@ class Redis
20
20
  def initialize(node_configs, options = {})
21
21
  @tag = options[:tag] || /^\{(.+?)\}/
22
22
  @ring = options[:ring] || HashRing.new
23
- @node_configs = node_configs.dup
23
+ @node_configs = node_configs.map(&:dup)
24
24
  @default_options = options.dup
25
25
  node_configs.each { |node_config| add_node(node_config) }
26
26
  @subscribed_node = nil
@@ -41,6 +41,8 @@ class Redis
41
41
  def add_node(options)
42
42
  options = { url: options } if options.is_a?(String)
43
43
  options = @default_options.merge(options)
44
+ options.delete(:tag)
45
+ options.delete(:ring)
44
46
  @ring.add_node Redis.new(options)
45
47
  end
46
48
 
@@ -64,6 +66,10 @@ class Redis
64
66
  on_each_node :quit
65
67
  end
66
68
 
69
+ def close
70
+ on_each_node :close
71
+ end
72
+
67
73
  # Asynchronously save the dataset to disk.
68
74
  def bgsave
69
75
  on_each_node :bgsave
@@ -115,13 +121,18 @@ class Redis
115
121
  end
116
122
 
117
123
  # Set a key's time to live in seconds.
118
- def expire(key, seconds)
119
- node_for(key).expire(key, seconds)
124
+ def expire(key, seconds, **kwargs)
125
+ node_for(key).expire(key, seconds, **kwargs)
120
126
  end
121
127
 
122
128
  # Set the expiration for a key as a UNIX timestamp.
123
- def expireat(key, unix_time)
124
- node_for(key).expireat(key, unix_time)
129
+ def expireat(key, unix_time, **kwargs)
130
+ node_for(key).expireat(key, unix_time, **kwargs)
131
+ end
132
+
133
+ # Get the expiration for a key as a UNIX timestamp.
134
+ def expiretime(key)
135
+ node_for(key).expiretime(key)
125
136
  end
126
137
 
127
138
  # Get the time to live (in seconds) for a key.
@@ -130,13 +141,18 @@ class Redis
130
141
  end
131
142
 
132
143
  # Set a key's time to live in milliseconds.
133
- def pexpire(key, milliseconds)
134
- node_for(key).pexpire(key, milliseconds)
144
+ def pexpire(key, milliseconds, **kwarg)
145
+ node_for(key).pexpire(key, milliseconds, **kwarg)
135
146
  end
136
147
 
137
148
  # Set the expiration for a key as number of milliseconds from UNIX Epoch.
138
- def pexpireat(key, ms_unix_time)
139
- node_for(key).pexpireat(key, ms_unix_time)
149
+ def pexpireat(key, ms_unix_time, **kwarg)
150
+ node_for(key).pexpireat(key, ms_unix_time, **kwarg)
151
+ end
152
+
153
+ # Get the expiration for a key as number of milliseconds from UNIX Epoch.
154
+ def pexpiretime(key)
155
+ node_for(key).pexpiretime(key)
140
156
  end
141
157
 
142
158
  # Get the time to live (in milliseconds) for a key.
@@ -161,6 +177,7 @@ class Redis
161
177
 
162
178
  # Delete a key.
163
179
  def del(*args)
180
+ args.flatten!(1)
164
181
  keys_per_node = args.group_by { |key| node_for(key) }
165
182
  keys_per_node.inject(0) do |sum, (node, keys)|
166
183
  sum + node.del(*keys)
@@ -169,6 +186,7 @@ class Redis
169
186
 
170
187
  # Unlink keys.
171
188
  def unlink(*args)
189
+ args.flatten!(1)
172
190
  keys_per_node = args.group_by { |key| node_for(key) }
173
191
  keys_per_node.inject(0) do |sum, (node, keys)|
174
192
  sum + node.unlink(*keys)
@@ -177,27 +195,16 @@ class Redis
177
195
 
178
196
  # Determine if a key exists.
179
197
  def exists(*args)
180
- if !Redis.exists_returns_integer && args.size == 1
181
- message = "`Redis#exists(key)` will return an Integer in redis-rb 4.3, if you want to keep the old behavior, " \
182
- "use `exists?` instead. To opt-in to the new behavior now you can set Redis.exists_returns_integer = true. " \
183
- "(#{::Kernel.caller(1, 1).first})\n"
184
-
185
- if defined?(::Warning)
186
- ::Warning.warn(message)
187
- else
188
- warn(message)
189
- end
190
- exists?(*args)
191
- else
192
- keys_per_node = args.group_by { |key| node_for(key) }
193
- keys_per_node.inject(0) do |sum, (node, keys)|
194
- sum + node._exists(*keys)
195
- end
198
+ args.flatten!(1)
199
+ keys_per_node = args.group_by { |key| node_for(key) }
200
+ keys_per_node.inject(0) do |sum, (node, keys)|
201
+ sum + node.exists(*keys)
196
202
  end
197
203
  end
198
204
 
199
205
  # Determine if any of the keys exists.
200
206
  def exists?(*args)
207
+ args.flatten!(1)
201
208
  keys_per_node = args.group_by { |key| node_for(key) }
202
209
  keys_per_node.each do |node, keys|
203
210
  return true if node.exists?(*keys)
@@ -215,6 +222,13 @@ class Redis
215
222
  node_for(key).move(key, db)
216
223
  end
217
224
 
225
+ # Copy a value from one key to another.
226
+ def copy(source, destination, **options)
227
+ ensure_same_node(:copy, [source, destination]) do |node|
228
+ node.copy(source, destination, **options)
229
+ end
230
+ end
231
+
218
232
  # Return a random key from the keyspace.
219
233
  def randomkey
220
234
  raise CannotDistribute, :randomkey
@@ -294,7 +308,7 @@ class Redis
294
308
  end
295
309
 
296
310
  # Set multiple keys to multiple values.
297
- def mset(*_args)
311
+ def mset(*)
298
312
  raise CannotDistribute, :mset
299
313
  end
300
314
 
@@ -303,7 +317,7 @@ class Redis
303
317
  end
304
318
 
305
319
  # Set multiple keys to multiple values, only if none of the keys exist.
306
- def msetnx(*_args)
320
+ def msetnx(*)
307
321
  raise CannotDistribute, :msetnx
308
322
  end
309
323
 
@@ -316,13 +330,25 @@ class Redis
316
330
  node_for(key).get(key)
317
331
  end
318
332
 
333
+ # Get the value of a key and delete it.
334
+ def getdel(key)
335
+ node_for(key).getdel(key)
336
+ end
337
+
338
+ # Get the value of a key and sets its time to live based on options.
339
+ def getex(key, **options)
340
+ node_for(key).getex(key, **options)
341
+ end
342
+
319
343
  # Get the values of all the given keys as an Array.
320
344
  def mget(*keys)
345
+ keys.flatten!(1)
321
346
  mapped_mget(*keys).values_at(*keys)
322
347
  end
323
348
 
324
349
  # Get the values of all the given keys as a Hash.
325
350
  def mapped_mget(*keys)
351
+ keys.flatten!(1)
326
352
  keys.group_by { |k| node_for k }.inject({}) do |results, (node, subkeys)|
327
353
  results.merge! node.mapped_mget(*subkeys)
328
354
  end
@@ -354,20 +380,21 @@ class Redis
354
380
  end
355
381
 
356
382
  # Count the number of set bits in a range of the string value stored at key.
357
- def bitcount(key, start = 0, stop = -1)
358
- node_for(key).bitcount(key, start, stop)
383
+ def bitcount(key, start = 0, stop = -1, scale: nil)
384
+ node_for(key).bitcount(key, start, stop, scale: scale)
359
385
  end
360
386
 
361
387
  # Perform a bitwise operation between strings and store the resulting string in a key.
362
388
  def bitop(operation, destkey, *keys)
389
+ keys.flatten!(1)
363
390
  ensure_same_node(:bitop, [destkey] + keys) do |node|
364
- node.bitop(operation, destkey, *keys)
391
+ node.bitop(operation, destkey, keys)
365
392
  end
366
393
  end
367
394
 
368
395
  # Return the position of the first bit set to 1 or 0 in a string.
369
- def bitpos(key, bit, start = nil, stop = nil)
370
- node_for(key).bitpos(key, bit, start, stop)
396
+ def bitpos(key, bit, start = nil, stop = nil, scale: nil)
397
+ node_for(key).bitpos(key, bit, start, stop, scale: scale)
371
398
  end
372
399
 
373
400
  # Set the string value of a key and return its old value.
@@ -393,6 +420,21 @@ class Redis
393
420
  node_for(key).llen(key)
394
421
  end
395
422
 
423
+ # Remove the first/last element in a list, append/prepend it to another list and return it.
424
+ def lmove(source, destination, where_source, where_destination)
425
+ ensure_same_node(:lmove, [source, destination]) do |node|
426
+ node.lmove(source, destination, where_source, where_destination)
427
+ end
428
+ end
429
+
430
+ # Remove the first/last element in a list and append/prepend it
431
+ # to another list and return it, or block until one is available.
432
+ def blmove(source, destination, where_source, where_destination, timeout: 0)
433
+ ensure_same_node(:lmove, [source, destination]) do |node|
434
+ node.blmove(source, destination, where_source, where_destination, timeout: timeout)
435
+ end
436
+ end
437
+
396
438
  # Prepend one or more values to a list.
397
439
  def lpush(key, value)
398
440
  node_for(key).lpush(key, value)
@@ -435,22 +477,15 @@ class Redis
435
477
  timeout = if args.last.is_a?(Hash)
436
478
  options = args.pop
437
479
  options[:timeout]
438
- elsif args.last.respond_to?(:to_int)
439
- # Issue deprecation notice in obnoxious mode...
440
- args.pop.to_int
441
- end
442
-
443
- if args.size > 1
444
- # Issue deprecation notice in obnoxious mode...
445
480
  end
446
481
 
447
- keys = args.flatten
482
+ args.flatten!(1)
448
483
 
449
- ensure_same_node(cmd, keys) do |node|
484
+ ensure_same_node(cmd, args) do |node|
450
485
  if timeout
451
- node.__send__(cmd, keys, timeout: timeout)
486
+ node.__send__(cmd, args, timeout: timeout)
452
487
  else
453
- node.__send__(cmd, keys)
488
+ node.__send__(cmd, args)
454
489
  end
455
490
  end
456
491
  end
@@ -461,6 +496,18 @@ class Redis
461
496
  _bpop(:blpop, args)
462
497
  end
463
498
 
499
+ def bzpopmax(*args)
500
+ _bpop(:bzpopmax, args) do |reply|
501
+ reply.is_a?(Array) ? [reply[0], reply[1], Floatify.call(reply[2])] : reply
502
+ end
503
+ end
504
+
505
+ def bzpopmin(*args)
506
+ _bpop(:bzpopmin, args) do |reply|
507
+ reply.is_a?(Array) ? [reply[0], reply[1], Floatify.call(reply[2])] : reply
508
+ end
509
+ end
510
+
464
511
  # Remove and get the last element in a list, or block until one is
465
512
  # available.
466
513
  def brpop(*args)
@@ -469,9 +516,9 @@ class Redis
469
516
 
470
517
  # Pop a value from a list, push it to another list and return it; or block
471
518
  # until one is available.
472
- def brpoplpush(source, destination, deprecated_timeout = 0, **options)
519
+ def brpoplpush(source, destination, **options)
473
520
  ensure_same_node(:brpoplpush, [source, destination]) do |node|
474
- node.brpoplpush(source, destination, deprecated_timeout, **options)
521
+ node.brpoplpush(source, destination, **options)
475
522
  end
476
523
  end
477
524
 
@@ -505,19 +552,43 @@ class Redis
505
552
  node_for(key).ltrim(key, start, stop)
506
553
  end
507
554
 
555
+ # Iterate over keys, blocking and removing elements from the first non empty liist found.
556
+ def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
557
+ ensure_same_node(:blmpop, keys) do |node|
558
+ node.blmpop(timeout, *keys, modifier: modifier, count: count)
559
+ end
560
+ end
561
+
562
+ # Iterate over keys, removing elements from the first non list found.
563
+ def lmpop(*keys, modifier: "LEFT", count: nil)
564
+ ensure_same_node(:lmpop, keys) do |node|
565
+ node.lmpop(*keys, modifier: modifier, count: count)
566
+ end
567
+ end
568
+
508
569
  # Get the number of members in a set.
509
570
  def scard(key)
510
571
  node_for(key).scard(key)
511
572
  end
512
573
 
513
574
  # Add one or more members to a set.
514
- def sadd(key, member)
515
- node_for(key).sadd(key, member)
575
+ def sadd(key, *members)
576
+ node_for(key).sadd(key, *members)
577
+ end
578
+
579
+ # Add one or more members to a set.
580
+ def sadd?(key, *members)
581
+ node_for(key).sadd?(key, *members)
516
582
  end
517
583
 
518
584
  # Remove one or more members from a set.
519
- def srem(key, member)
520
- node_for(key).srem(key, member)
585
+ def srem(key, *members)
586
+ node_for(key).srem(key, *members)
587
+ end
588
+
589
+ # Remove one or more members from a set.
590
+ def srem?(key, *members)
591
+ node_for(key).srem?(key, *members)
521
592
  end
522
593
 
523
594
  # Remove and return a random member from a set.
@@ -542,6 +613,11 @@ class Redis
542
613
  node_for(key).sismember(key, member)
543
614
  end
544
615
 
616
+ # Determine if multiple values are members of a set.
617
+ def smismember(key, *members)
618
+ node_for(key).smismember(key, *members)
619
+ end
620
+
545
621
  # Get all the members in a set.
546
622
  def smembers(key)
547
623
  node_for(key).smembers(key)
@@ -559,43 +635,49 @@ class Redis
559
635
 
560
636
  # Subtract multiple sets.
561
637
  def sdiff(*keys)
638
+ keys.flatten!(1)
562
639
  ensure_same_node(:sdiff, keys) do |node|
563
- node.sdiff(*keys)
640
+ node.sdiff(keys)
564
641
  end
565
642
  end
566
643
 
567
644
  # Subtract multiple sets and store the resulting set in a key.
568
645
  def sdiffstore(destination, *keys)
569
- ensure_same_node(:sdiffstore, [destination] + keys) do |node|
570
- node.sdiffstore(destination, *keys)
646
+ keys.flatten!(1)
647
+ ensure_same_node(:sdiffstore, [destination].concat(keys)) do |node|
648
+ node.sdiffstore(destination, keys)
571
649
  end
572
650
  end
573
651
 
574
652
  # Intersect multiple sets.
575
653
  def sinter(*keys)
654
+ keys.flatten!(1)
576
655
  ensure_same_node(:sinter, keys) do |node|
577
- node.sinter(*keys)
656
+ node.sinter(keys)
578
657
  end
579
658
  end
580
659
 
581
660
  # Intersect multiple sets and store the resulting set in a key.
582
661
  def sinterstore(destination, *keys)
583
- ensure_same_node(:sinterstore, [destination] + keys) do |node|
584
- node.sinterstore(destination, *keys)
662
+ keys.flatten!(1)
663
+ ensure_same_node(:sinterstore, [destination].concat(keys)) do |node|
664
+ node.sinterstore(destination, keys)
585
665
  end
586
666
  end
587
667
 
588
668
  # Add multiple sets.
589
669
  def sunion(*keys)
670
+ keys.flatten!(1)
590
671
  ensure_same_node(:sunion, keys) do |node|
591
- node.sunion(*keys)
672
+ node.sunion(keys)
592
673
  end
593
674
  end
594
675
 
595
676
  # Add multiple sets and store the resulting set in a key.
596
677
  def sunionstore(destination, *keys)
597
- ensure_same_node(:sunionstore, [destination] + keys) do |node|
598
- node.sunionstore(destination, *keys)
678
+ keys.flatten!(1)
679
+ ensure_same_node(:sunionstore, [destination].concat(keys)) do |node|
680
+ node.sunionstore(destination, keys)
599
681
  end
600
682
  end
601
683
 
@@ -626,11 +708,43 @@ class Redis
626
708
  node_for(key).zscore(key, member)
627
709
  end
628
710
 
629
- # Return a range of members in a sorted set, by index.
711
+ # Get one or more random members from a sorted set.
712
+ def zrandmember(key, count = nil, **options)
713
+ node_for(key).zrandmember(key, count, **options)
714
+ end
715
+
716
+ # Get the scores associated with the given members in a sorted set.
717
+ def zmscore(key, *members)
718
+ node_for(key).zmscore(key, *members)
719
+ end
720
+
721
+ # Iterate over keys, blocking and removing members from the first non empty sorted set found.
722
+ def bzmpop(timeout, *keys, modifier: "MIN", count: nil)
723
+ ensure_same_node(:bzmpop, keys) do |node|
724
+ node.bzmpop(timeout, *keys, modifier: modifier, count: count)
725
+ end
726
+ end
727
+
728
+ # Iterate over keys, removing members from the first non empty sorted set found.
729
+ def zmpop(*keys, modifier: "MIN", count: nil)
730
+ ensure_same_node(:zmpop, keys) do |node|
731
+ node.zmpop(*keys, modifier: modifier, count: count)
732
+ end
733
+ end
734
+
735
+ # Return a range of members in a sorted set, by index, score or lexicographical ordering.
630
736
  def zrange(key, start, stop, **options)
631
737
  node_for(key).zrange(key, start, stop, **options)
632
738
  end
633
739
 
740
+ # Select a range of members in a sorted set, by index, score or lexicographical ordering
741
+ # and store the resulting sorted set in a new key.
742
+ def zrangestore(dest_key, src_key, start, stop, **options)
743
+ ensure_same_node(:zrangestore, [dest_key, src_key]) do |node|
744
+ node.zrangestore(dest_key, src_key, start, stop, **options)
745
+ end
746
+ end
747
+
634
748
  # Return a range of members in a sorted set, by index, with scores ordered
635
749
  # from high to low.
636
750
  def zrevrange(key, start, stop, **options)
@@ -638,14 +752,14 @@ class Redis
638
752
  end
639
753
 
640
754
  # Determine the index of a member in a sorted set.
641
- def zrank(key, member)
642
- node_for(key).zrank(key, member)
755
+ def zrank(key, member, **options)
756
+ node_for(key).zrank(key, member, **options)
643
757
  end
644
758
 
645
759
  # Determine the index of a member in a sorted set, with scores ordered from
646
760
  # high to low.
647
- def zrevrank(key, member)
648
- node_for(key).zrevrank(key, member)
761
+ def zrevrank(key, member, **options)
762
+ node_for(key).zrevrank(key, member, **options)
649
763
  end
650
764
 
651
765
  # Remove all members in a sorted set within the given indexes.
@@ -674,21 +788,56 @@ class Redis
674
788
  node_for(key).zcount(key, min, max)
675
789
  end
676
790
 
791
+ # Get the intersection of multiple sorted sets
792
+ def zinter(*keys, **options)
793
+ keys.flatten!(1)
794
+ ensure_same_node(:zinter, keys) do |node|
795
+ node.zinter(keys, **options)
796
+ end
797
+ end
798
+
677
799
  # Intersect multiple sorted sets and store the resulting sorted set in a new
678
800
  # key.
679
- def zinterstore(destination, keys, **options)
680
- ensure_same_node(:zinterstore, [destination] + keys) do |node|
801
+ def zinterstore(destination, *keys, **options)
802
+ keys.flatten!(1)
803
+ ensure_same_node(:zinterstore, [destination].concat(keys)) do |node|
681
804
  node.zinterstore(destination, keys, **options)
682
805
  end
683
806
  end
684
807
 
808
+ # Return the union of multiple sorted sets.
809
+ def zunion(*keys, **options)
810
+ keys.flatten!(1)
811
+ ensure_same_node(:zunion, keys) do |node|
812
+ node.zunion(keys, **options)
813
+ end
814
+ end
815
+
685
816
  # Add multiple sorted sets and store the resulting sorted set in a new key.
686
- def zunionstore(destination, keys, **options)
687
- ensure_same_node(:zunionstore, [destination] + keys) do |node|
817
+ def zunionstore(destination, *keys, **options)
818
+ keys.flatten!(1)
819
+ ensure_same_node(:zunionstore, [destination].concat(keys)) do |node|
688
820
  node.zunionstore(destination, keys, **options)
689
821
  end
690
822
  end
691
823
 
824
+ # Return the difference between the first and all successive input sorted sets.
825
+ def zdiff(*keys, **options)
826
+ keys.flatten!(1)
827
+ ensure_same_node(:zdiff, keys) do |node|
828
+ node.zdiff(keys, **options)
829
+ end
830
+ end
831
+
832
+ # Compute the difference between the first and all successive input sorted sets
833
+ # and store the resulting sorted set in a new key.
834
+ def zdiffstore(destination, *keys, **options)
835
+ keys.flatten!(1)
836
+ ensure_same_node(:zdiffstore, [destination] + keys) do |node|
837
+ node.zdiffstore(destination, keys, **options)
838
+ end
839
+ end
840
+
692
841
  # Get the number of fields in a hash.
693
842
  def hlen(key)
694
843
  node_for(key).hlen(key)
@@ -710,7 +859,7 @@ class Redis
710
859
  end
711
860
 
712
861
  def mapped_hmset(key, hash)
713
- node_for(key).hmset(key, *hash.to_a.flatten)
862
+ node_for(key).hmset(key, hash)
714
863
  end
715
864
 
716
865
  # Get the value of a hash field.
@@ -720,16 +869,23 @@ class Redis
720
869
 
721
870
  # Get the values of all the given hash fields.
722
871
  def hmget(key, *fields)
723
- node_for(key).hmget(key, *fields)
872
+ fields.flatten!(1)
873
+ node_for(key).hmget(key, fields)
724
874
  end
725
875
 
726
876
  def mapped_hmget(key, *fields)
727
- Hash[*fields.zip(hmget(key, *fields)).flatten]
877
+ fields.flatten!(1)
878
+ node_for(key).mapped_hmget(key, fields)
879
+ end
880
+
881
+ def hrandfield(key, count = nil, **options)
882
+ node_for(key).hrandfield(key, count, **options)
728
883
  end
729
884
 
730
885
  # Delete one or more hash fields.
731
886
  def hdel(key, *fields)
732
- node_for(key).hdel(key, *fields)
887
+ fields.flatten!(1)
888
+ node_for(key).hdel(key, fields)
733
889
  end
734
890
 
735
891
  # Determine if a hash field exists.
@@ -786,18 +942,22 @@ class Redis
786
942
 
787
943
  # Stop listening for messages posted to the given channels.
788
944
  def unsubscribe(*channels)
789
- raise "Can't unsubscribe if not subscribed." unless subscribed?
945
+ raise SubscriptionError, "Can't unsubscribe if not subscribed." unless subscribed?
790
946
 
791
947
  @subscribed_node.unsubscribe(*channels)
792
948
  end
793
949
 
794
950
  # Listen for messages published to channels matching the given patterns.
951
+ # See the [Redis Server PSUBSCRIBE documentation](https://redis.io/docs/latest/commands/psubscribe/)
952
+ # for further details
795
953
  def psubscribe(*channels, &block)
796
954
  raise NotImplementedError
797
955
  end
798
956
 
799
957
  # Stop listening for messages posted to channels matching the given
800
958
  # patterns.
959
+ # See the [Redis Server PUNSUBSCRIBE documentation](https://redis.io/docs/latest/commands/punsubscribe/)
960
+ # for further details
801
961
  def punsubscribe(*channels)
802
962
  raise NotImplementedError
803
963
  end
@@ -833,9 +993,7 @@ class Redis
833
993
  def multi(&block)
834
994
  raise CannotDistribute, :multi unless @watch_key
835
995
 
836
- result = node_for(@watch_key).multi(&block)
837
- @watch_key = nil if block_given?
838
- result
996
+ node_for(@watch_key).multi(&block)
839
997
  end
840
998
 
841
999
  # Execute all commands issued after MULTI.
@@ -925,7 +1083,8 @@ class Redis
925
1083
  end
926
1084
 
927
1085
  def key_tag(key)
928
- key.to_s[@tag, 1] if @tag
1086
+ key = key.to_s
1087
+ key[@tag, 1] if key.match?(@tag)
929
1088
  end
930
1089
 
931
1090
  def ensure_same_node(command, keys)
data/lib/redis/errors.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  class Redis
4
4
  # Base error for all redis-rb errors.
5
- class BaseError < RuntimeError
5
+ class BaseError < StandardError
6
6
  end
7
7
 
8
8
  # Raised by the connection when a protocol error occurs.
@@ -20,6 +20,20 @@ class Redis
20
20
  class CommandError < BaseError
21
21
  end
22
22
 
23
+ class PermissionError < CommandError
24
+ end
25
+
26
+ class WrongTypeError < CommandError
27
+ end
28
+
29
+ class OutOfMemoryError < CommandError
30
+ end
31
+
32
+ if defined?(RedisClient::NoScriptError)
33
+ class NoScriptError < CommandError
34
+ end
35
+ end
36
+
23
37
  # Base error for connection related errors.
24
38
  class BaseConnectionError < BaseError
25
39
  end
@@ -40,49 +54,14 @@ class Redis
40
54
  class InheritedError < BaseConnectionError
41
55
  end
42
56
 
57
+ # Generally raised during Redis failover scenarios
58
+ class ReadOnlyError < BaseConnectionError
59
+ end
60
+
43
61
  # Raised when client options are invalid.
44
62
  class InvalidClientOptionError < BaseError
45
63
  end
46
64
 
47
- class Cluster
48
- # Raised when client connected to redis as cluster mode
49
- # and some cluster subcommands were called.
50
- class OrchestrationCommandNotSupported < BaseError
51
- def initialize(command, subcommand = '')
52
- str = [command, subcommand].map(&:to_s).reject(&:empty?).join(' ').upcase
53
- msg = "#{str} command should be used with care "\
54
- 'only by applications orchestrating Redis Cluster, like redis-trib, '\
55
- 'and the command if used out of the right context can leave the cluster '\
56
- 'in a wrong state or cause data loss.'
57
- super(msg)
58
- end
59
- end
60
-
61
- # Raised when error occurs on any node of cluster.
62
- class CommandErrorCollection < BaseError
63
- attr_reader :errors
64
-
65
- # @param errors [Hash{String => Redis::CommandError}]
66
- # @param error_message [String]
67
- def initialize(errors, error_message = 'Command errors were replied on any node')
68
- @errors = errors
69
- super(error_message)
70
- end
71
- end
72
-
73
- # Raised when cluster client can't select node.
74
- class AmbiguousNodeError < BaseError
75
- def initialize(command)
76
- super("Cluster client doesn't know which node the #{command} command should be sent to.")
77
- end
78
- end
79
-
80
- # Raised when commands in pipelining include cross slot keys.
81
- class CrossSlotPipeliningError < BaseError
82
- def initialize(keys)
83
- super("Cluster client couldn't send pipelining to single node. "\
84
- "The commands include cross slot keys. #{keys}")
85
- end
86
- end
65
+ class SubscriptionError < BaseError
87
66
  end
88
67
  end