redis 4.2.5 → 5.0.7

Sign up to get free protection for your applications and to get access to all the features.
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