redis 4.2.5 → 5.0.7

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 +167 -0
  3. data/README.md +102 -162
  4. data/lib/redis/client.rb +84 -589
  5. data/lib/redis/commands/bitmaps.rb +66 -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 +254 -0
  10. data/lib/redis/commands/hyper_log_log.rb +37 -0
  11. data/lib/redis/commands/keys.rb +437 -0
  12. data/lib/redis/commands/lists.rb +339 -0
  13. data/lib/redis/commands/pubsub.rb +54 -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 +214 -0
  17. data/lib/redis/commands/sorted_sets.rb +884 -0
  18. data/lib/redis/commands/streams.rb +402 -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 +237 -0
  22. data/lib/redis/distributed.rb +220 -75
  23. data/lib/redis/errors.rb +15 -41
  24. data/lib/redis/hash_ring.rb +26 -26
  25. data/lib/redis/pipeline.rb +66 -120
  26. data/lib/redis/subscribe.rb +23 -15
  27. data/lib/redis/version.rb +1 -1
  28. data/lib/redis.rb +110 -3441
  29. metadata +27 -54
  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 -90
  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,13 @@ 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)
125
131
  end
126
132
 
127
133
  # Get the time to live (in seconds) for a key.
@@ -130,13 +136,13 @@ class Redis
130
136
  end
131
137
 
132
138
  # Set a key's time to live in milliseconds.
133
- def pexpire(key, milliseconds)
134
- node_for(key).pexpire(key, milliseconds)
139
+ def pexpire(key, milliseconds, **kwarg)
140
+ node_for(key).pexpire(key, milliseconds, **kwarg)
135
141
  end
136
142
 
137
143
  # 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)
144
+ def pexpireat(key, ms_unix_time, **kwarg)
145
+ node_for(key).pexpireat(key, ms_unix_time, **kwarg)
140
146
  end
141
147
 
142
148
  # Get the time to live (in milliseconds) for a key.
@@ -161,6 +167,7 @@ class Redis
161
167
 
162
168
  # Delete a key.
163
169
  def del(*args)
170
+ args.flatten!(1)
164
171
  keys_per_node = args.group_by { |key| node_for(key) }
165
172
  keys_per_node.inject(0) do |sum, (node, keys)|
166
173
  sum + node.del(*keys)
@@ -169,6 +176,7 @@ class Redis
169
176
 
170
177
  # Unlink keys.
171
178
  def unlink(*args)
179
+ args.flatten!(1)
172
180
  keys_per_node = args.group_by { |key| node_for(key) }
173
181
  keys_per_node.inject(0) do |sum, (node, keys)|
174
182
  sum + node.unlink(*keys)
@@ -177,27 +185,16 @@ class Redis
177
185
 
178
186
  # Determine if a key exists.
179
187
  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
188
+ args.flatten!(1)
189
+ keys_per_node = args.group_by { |key| node_for(key) }
190
+ keys_per_node.inject(0) do |sum, (node, keys)|
191
+ sum + node.exists(*keys)
196
192
  end
197
193
  end
198
194
 
199
195
  # Determine if any of the keys exists.
200
196
  def exists?(*args)
197
+ args.flatten!(1)
201
198
  keys_per_node = args.group_by { |key| node_for(key) }
202
199
  keys_per_node.each do |node, keys|
203
200
  return true if node.exists?(*keys)
@@ -215,6 +212,13 @@ class Redis
215
212
  node_for(key).move(key, db)
216
213
  end
217
214
 
215
+ # Copy a value from one key to another.
216
+ def copy(source, destination, **options)
217
+ ensure_same_node(:copy, [source, destination]) do |node|
218
+ node.copy(source, destination, **options)
219
+ end
220
+ end
221
+
218
222
  # Return a random key from the keyspace.
219
223
  def randomkey
220
224
  raise CannotDistribute, :randomkey
@@ -294,7 +298,7 @@ class Redis
294
298
  end
295
299
 
296
300
  # Set multiple keys to multiple values.
297
- def mset(*_args)
301
+ def mset(*)
298
302
  raise CannotDistribute, :mset
299
303
  end
300
304
 
@@ -303,7 +307,7 @@ class Redis
303
307
  end
304
308
 
305
309
  # Set multiple keys to multiple values, only if none of the keys exist.
306
- def msetnx(*_args)
310
+ def msetnx(*)
307
311
  raise CannotDistribute, :msetnx
308
312
  end
309
313
 
@@ -316,13 +320,25 @@ class Redis
316
320
  node_for(key).get(key)
317
321
  end
318
322
 
323
+ # Get the value of a key and delete it.
324
+ def getdel(key)
325
+ node_for(key).getdel(key)
326
+ end
327
+
328
+ # Get the value of a key and sets its time to live based on options.
329
+ def getex(key, **options)
330
+ node_for(key).getex(key, **options)
331
+ end
332
+
319
333
  # Get the values of all the given keys as an Array.
320
334
  def mget(*keys)
335
+ keys.flatten!(1)
321
336
  mapped_mget(*keys).values_at(*keys)
322
337
  end
323
338
 
324
339
  # Get the values of all the given keys as a Hash.
325
340
  def mapped_mget(*keys)
341
+ keys.flatten!(1)
326
342
  keys.group_by { |k| node_for k }.inject({}) do |results, (node, subkeys)|
327
343
  results.merge! node.mapped_mget(*subkeys)
328
344
  end
@@ -360,8 +376,9 @@ class Redis
360
376
 
361
377
  # Perform a bitwise operation between strings and store the resulting string in a key.
362
378
  def bitop(operation, destkey, *keys)
379
+ keys.flatten!(1)
363
380
  ensure_same_node(:bitop, [destkey] + keys) do |node|
364
- node.bitop(operation, destkey, *keys)
381
+ node.bitop(operation, destkey, keys)
365
382
  end
366
383
  end
367
384
 
@@ -393,6 +410,21 @@ class Redis
393
410
  node_for(key).llen(key)
394
411
  end
395
412
 
413
+ # Remove the first/last element in a list, append/prepend it to another list and return it.
414
+ def lmove(source, destination, where_source, where_destination)
415
+ ensure_same_node(:lmove, [source, destination]) do |node|
416
+ node.lmove(source, destination, where_source, where_destination)
417
+ end
418
+ end
419
+
420
+ # Remove the first/last element in a list and append/prepend it
421
+ # to another list and return it, or block until one is available.
422
+ def blmove(source, destination, where_source, where_destination, timeout: 0)
423
+ ensure_same_node(:lmove, [source, destination]) do |node|
424
+ node.blmove(source, destination, where_source, where_destination, timeout: timeout)
425
+ end
426
+ end
427
+
396
428
  # Prepend one or more values to a list.
397
429
  def lpush(key, value)
398
430
  node_for(key).lpush(key, value)
@@ -413,14 +445,14 @@ class Redis
413
445
  node_for(key).rpushx(key, value)
414
446
  end
415
447
 
416
- # Remove and get the first element in a list.
417
- def lpop(key)
418
- node_for(key).lpop(key)
448
+ # Remove and get the first elements in a list.
449
+ def lpop(key, count = nil)
450
+ node_for(key).lpop(key, count)
419
451
  end
420
452
 
421
- # Remove and get the last element in a list.
422
- def rpop(key)
423
- node_for(key).rpop(key)
453
+ # Remove and get the last elements in a list.
454
+ def rpop(key, count = nil)
455
+ node_for(key).rpop(key, count)
424
456
  end
425
457
 
426
458
  # Remove the last element in a list, append it to another list and return
@@ -435,22 +467,15 @@ class Redis
435
467
  timeout = if args.last.is_a?(Hash)
436
468
  options = args.pop
437
469
  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
470
  end
446
471
 
447
- keys = args.flatten
472
+ args.flatten!(1)
448
473
 
449
- ensure_same_node(cmd, keys) do |node|
474
+ ensure_same_node(cmd, args) do |node|
450
475
  if timeout
451
- node.__send__(cmd, keys, timeout: timeout)
476
+ node.__send__(cmd, args, timeout: timeout)
452
477
  else
453
- node.__send__(cmd, keys)
478
+ node.__send__(cmd, args)
454
479
  end
455
480
  end
456
481
  end
@@ -461,6 +486,18 @@ class Redis
461
486
  _bpop(:blpop, args)
462
487
  end
463
488
 
489
+ def bzpopmax(*args)
490
+ _bpop(:bzpopmax, args) do |reply|
491
+ reply.is_a?(Array) ? [reply[0], reply[1], Floatify.call(reply[2])] : reply
492
+ end
493
+ end
494
+
495
+ def bzpopmin(*args)
496
+ _bpop(:bzpopmin, args) do |reply|
497
+ reply.is_a?(Array) ? [reply[0], reply[1], Floatify.call(reply[2])] : reply
498
+ end
499
+ end
500
+
464
501
  # Remove and get the last element in a list, or block until one is
465
502
  # available.
466
503
  def brpop(*args)
@@ -469,9 +506,9 @@ class Redis
469
506
 
470
507
  # Pop a value from a list, push it to another list and return it; or block
471
508
  # until one is available.
472
- def brpoplpush(source, destination, deprecated_timeout = 0, **options)
509
+ def brpoplpush(source, destination, **options)
473
510
  ensure_same_node(:brpoplpush, [source, destination]) do |node|
474
- node.brpoplpush(source, destination, deprecated_timeout, **options)
511
+ node.brpoplpush(source, destination, **options)
475
512
  end
476
513
  end
477
514
 
@@ -505,19 +542,43 @@ class Redis
505
542
  node_for(key).ltrim(key, start, stop)
506
543
  end
507
544
 
545
+ # Iterate over keys, blocking and removing elements from the first non empty liist found.
546
+ def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
547
+ ensure_same_node(:blmpop, keys) do |node|
548
+ node.blmpop(timeout, *keys, modifier: modifier, count: count)
549
+ end
550
+ end
551
+
552
+ # Iterate over keys, removing elements from the first non list found.
553
+ def lmpop(*keys, modifier: "LEFT", count: nil)
554
+ ensure_same_node(:lmpop, keys) do |node|
555
+ node.lmpop(*keys, modifier: modifier, count: count)
556
+ end
557
+ end
558
+
508
559
  # Get the number of members in a set.
509
560
  def scard(key)
510
561
  node_for(key).scard(key)
511
562
  end
512
563
 
513
564
  # Add one or more members to a set.
514
- def sadd(key, member)
515
- node_for(key).sadd(key, member)
565
+ def sadd(key, *members)
566
+ node_for(key).sadd(key, *members)
567
+ end
568
+
569
+ # Add one or more members to a set.
570
+ def sadd?(key, *members)
571
+ node_for(key).sadd?(key, *members)
516
572
  end
517
573
 
518
574
  # Remove one or more members from a set.
519
- def srem(key, member)
520
- node_for(key).srem(key, member)
575
+ def srem(key, *members)
576
+ node_for(key).srem(key, *members)
577
+ end
578
+
579
+ # Remove one or more members from a set.
580
+ def srem?(key, *members)
581
+ node_for(key).srem?(key, *members)
521
582
  end
522
583
 
523
584
  # Remove and return a random member from a set.
@@ -542,6 +603,11 @@ class Redis
542
603
  node_for(key).sismember(key, member)
543
604
  end
544
605
 
606
+ # Determine if multiple values are members of a set.
607
+ def smismember(key, *members)
608
+ node_for(key).smismember(key, *members)
609
+ end
610
+
545
611
  # Get all the members in a set.
546
612
  def smembers(key)
547
613
  node_for(key).smembers(key)
@@ -559,43 +625,49 @@ class Redis
559
625
 
560
626
  # Subtract multiple sets.
561
627
  def sdiff(*keys)
628
+ keys.flatten!(1)
562
629
  ensure_same_node(:sdiff, keys) do |node|
563
- node.sdiff(*keys)
630
+ node.sdiff(keys)
564
631
  end
565
632
  end
566
633
 
567
634
  # Subtract multiple sets and store the resulting set in a key.
568
635
  def sdiffstore(destination, *keys)
569
- ensure_same_node(:sdiffstore, [destination] + keys) do |node|
570
- node.sdiffstore(destination, *keys)
636
+ keys.flatten!(1)
637
+ ensure_same_node(:sdiffstore, [destination].concat(keys)) do |node|
638
+ node.sdiffstore(destination, keys)
571
639
  end
572
640
  end
573
641
 
574
642
  # Intersect multiple sets.
575
643
  def sinter(*keys)
644
+ keys.flatten!(1)
576
645
  ensure_same_node(:sinter, keys) do |node|
577
- node.sinter(*keys)
646
+ node.sinter(keys)
578
647
  end
579
648
  end
580
649
 
581
650
  # Intersect multiple sets and store the resulting set in a key.
582
651
  def sinterstore(destination, *keys)
583
- ensure_same_node(:sinterstore, [destination] + keys) do |node|
584
- node.sinterstore(destination, *keys)
652
+ keys.flatten!(1)
653
+ ensure_same_node(:sinterstore, [destination].concat(keys)) do |node|
654
+ node.sinterstore(destination, keys)
585
655
  end
586
656
  end
587
657
 
588
658
  # Add multiple sets.
589
659
  def sunion(*keys)
660
+ keys.flatten!(1)
590
661
  ensure_same_node(:sunion, keys) do |node|
591
- node.sunion(*keys)
662
+ node.sunion(keys)
592
663
  end
593
664
  end
594
665
 
595
666
  # Add multiple sets and store the resulting set in a key.
596
667
  def sunionstore(destination, *keys)
597
- ensure_same_node(:sunionstore, [destination] + keys) do |node|
598
- node.sunionstore(destination, *keys)
668
+ keys.flatten!(1)
669
+ ensure_same_node(:sunionstore, [destination].concat(keys)) do |node|
670
+ node.sunionstore(destination, keys)
599
671
  end
600
672
  end
601
673
 
@@ -626,11 +698,43 @@ class Redis
626
698
  node_for(key).zscore(key, member)
627
699
  end
628
700
 
629
- # Return a range of members in a sorted set, by index.
701
+ # Get one or more random members from a sorted set.
702
+ def zrandmember(key, count = nil, **options)
703
+ node_for(key).zrandmember(key, count, **options)
704
+ end
705
+
706
+ # Get the scores associated with the given members in a sorted set.
707
+ def zmscore(key, *members)
708
+ node_for(key).zmscore(key, *members)
709
+ end
710
+
711
+ # Iterate over keys, blocking and removing members from the first non empty sorted set found.
712
+ def bzmpop(timeout, *keys, modifier: "MIN", count: nil)
713
+ ensure_same_node(:bzmpop, keys) do |node|
714
+ node.bzmpop(timeout, *keys, modifier: modifier, count: count)
715
+ end
716
+ end
717
+
718
+ # Iterate over keys, removing members from the first non empty sorted set found.
719
+ def zmpop(*keys, modifier: "MIN", count: nil)
720
+ ensure_same_node(:zmpop, keys) do |node|
721
+ node.zmpop(*keys, modifier: modifier, count: count)
722
+ end
723
+ end
724
+
725
+ # Return a range of members in a sorted set, by index, score or lexicographical ordering.
630
726
  def zrange(key, start, stop, **options)
631
727
  node_for(key).zrange(key, start, stop, **options)
632
728
  end
633
729
 
730
+ # Select a range of members in a sorted set, by index, score or lexicographical ordering
731
+ # and store the resulting sorted set in a new key.
732
+ def zrangestore(dest_key, src_key, start, stop, **options)
733
+ ensure_same_node(:zrangestore, [dest_key, src_key]) do |node|
734
+ node.zrangestore(dest_key, src_key, start, stop, **options)
735
+ end
736
+ end
737
+
634
738
  # Return a range of members in a sorted set, by index, with scores ordered
635
739
  # from high to low.
636
740
  def zrevrange(key, start, stop, **options)
@@ -674,21 +778,56 @@ class Redis
674
778
  node_for(key).zcount(key, min, max)
675
779
  end
676
780
 
781
+ # Get the intersection of multiple sorted sets
782
+ def zinter(*keys, **options)
783
+ keys.flatten!(1)
784
+ ensure_same_node(:zinter, keys) do |node|
785
+ node.zinter(keys, **options)
786
+ end
787
+ end
788
+
677
789
  # Intersect multiple sorted sets and store the resulting sorted set in a new
678
790
  # key.
679
- def zinterstore(destination, keys, **options)
680
- ensure_same_node(:zinterstore, [destination] + keys) do |node|
791
+ def zinterstore(destination, *keys, **options)
792
+ keys.flatten!(1)
793
+ ensure_same_node(:zinterstore, [destination].concat(keys)) do |node|
681
794
  node.zinterstore(destination, keys, **options)
682
795
  end
683
796
  end
684
797
 
798
+ # Return the union of multiple sorted sets.
799
+ def zunion(*keys, **options)
800
+ keys.flatten!(1)
801
+ ensure_same_node(:zunion, keys) do |node|
802
+ node.zunion(keys, **options)
803
+ end
804
+ end
805
+
685
806
  # 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|
807
+ def zunionstore(destination, *keys, **options)
808
+ keys.flatten!(1)
809
+ ensure_same_node(:zunionstore, [destination].concat(keys)) do |node|
688
810
  node.zunionstore(destination, keys, **options)
689
811
  end
690
812
  end
691
813
 
814
+ # Return the difference between the first and all successive input sorted sets.
815
+ def zdiff(*keys, **options)
816
+ keys.flatten!(1)
817
+ ensure_same_node(:zdiff, keys) do |node|
818
+ node.zdiff(keys, **options)
819
+ end
820
+ end
821
+
822
+ # Compute the difference between the first and all successive input sorted sets
823
+ # and store the resulting sorted set in a new key.
824
+ def zdiffstore(destination, *keys, **options)
825
+ keys.flatten!(1)
826
+ ensure_same_node(:zdiffstore, [destination] + keys) do |node|
827
+ node.zdiffstore(destination, keys, **options)
828
+ end
829
+ end
830
+
692
831
  # Get the number of fields in a hash.
693
832
  def hlen(key)
694
833
  node_for(key).hlen(key)
@@ -710,7 +849,7 @@ class Redis
710
849
  end
711
850
 
712
851
  def mapped_hmset(key, hash)
713
- node_for(key).hmset(key, *hash.to_a.flatten)
852
+ node_for(key).hmset(key, hash)
714
853
  end
715
854
 
716
855
  # Get the value of a hash field.
@@ -720,16 +859,23 @@ class Redis
720
859
 
721
860
  # Get the values of all the given hash fields.
722
861
  def hmget(key, *fields)
723
- node_for(key).hmget(key, *fields)
862
+ fields.flatten!(1)
863
+ node_for(key).hmget(key, fields)
724
864
  end
725
865
 
726
866
  def mapped_hmget(key, *fields)
727
- Hash[*fields.zip(hmget(key, *fields)).flatten]
867
+ fields.flatten!(1)
868
+ node_for(key).mapped_hmget(key, fields)
869
+ end
870
+
871
+ def hrandfield(key, count = nil, **options)
872
+ node_for(key).hrandfield(key, count, **options)
728
873
  end
729
874
 
730
875
  # Delete one or more hash fields.
731
876
  def hdel(key, *fields)
732
- node_for(key).hdel(key, *fields)
877
+ fields.flatten!(1)
878
+ node_for(key).hdel(key, fields)
733
879
  end
734
880
 
735
881
  # Determine if a hash field exists.
@@ -786,7 +932,7 @@ class Redis
786
932
 
787
933
  # Stop listening for messages posted to the given channels.
788
934
  def unsubscribe(*channels)
789
- raise "Can't unsubscribe if not subscribed." unless subscribed?
935
+ raise SubscriptionError, "Can't unsubscribe if not subscribed." unless subscribed?
790
936
 
791
937
  @subscribed_node.unsubscribe(*channels)
792
938
  end
@@ -833,9 +979,7 @@ class Redis
833
979
  def multi(&block)
834
980
  raise CannotDistribute, :multi unless @watch_key
835
981
 
836
- result = node_for(@watch_key).multi(&block)
837
- @watch_key = nil if block_given?
838
- result
982
+ node_for(@watch_key).multi(&block)
839
983
  end
840
984
 
841
985
  # Execute all commands issued after MULTI.
@@ -925,7 +1069,8 @@ class Redis
925
1069
  end
926
1070
 
927
1071
  def key_tag(key)
928
- key.to_s[@tag, 1] if @tag
1072
+ key = key.to_s
1073
+ key[@tag, 1] if key.match?(@tag)
929
1074
  end
930
1075
 
931
1076
  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,15 @@ 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
+
23
32
  # Base error for connection related errors.
24
33
  class BaseConnectionError < BaseError
25
34
  end
@@ -40,49 +49,14 @@ class Redis
40
49
  class InheritedError < BaseConnectionError
41
50
  end
42
51
 
52
+ # Generally raised during Redis failover scenarios
53
+ class ReadOnlyError < BaseConnectionError
54
+ end
55
+
43
56
  # Raised when client options are invalid.
44
57
  class InvalidClientOptionError < BaseError
45
58
  end
46
59
 
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
60
+ class SubscriptionError < BaseError
87
61
  end
88
62
  end