redis 4.4.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +150 -0
- data/README.md +95 -160
- data/lib/redis/client.rb +84 -608
- data/lib/redis/commands/bitmaps.rb +66 -0
- data/lib/redis/commands/cluster.rb +28 -0
- data/lib/redis/commands/connection.rb +53 -0
- data/lib/redis/commands/geo.rb +84 -0
- data/lib/redis/commands/hashes.rb +254 -0
- data/lib/redis/commands/hyper_log_log.rb +37 -0
- data/lib/redis/commands/keys.rb +437 -0
- data/lib/redis/commands/lists.rb +339 -0
- data/lib/redis/commands/pubsub.rb +54 -0
- data/lib/redis/commands/scripting.rb +114 -0
- data/lib/redis/commands/server.rb +188 -0
- data/lib/redis/commands/sets.rb +214 -0
- data/lib/redis/commands/sorted_sets.rb +884 -0
- data/lib/redis/commands/streams.rb +402 -0
- data/lib/redis/commands/strings.rb +314 -0
- data/lib/redis/commands/transactions.rb +115 -0
- data/lib/redis/commands.rb +237 -0
- data/lib/redis/distributed.rb +208 -70
- data/lib/redis/errors.rb +15 -41
- data/lib/redis/hash_ring.rb +26 -26
- data/lib/redis/pipeline.rb +66 -120
- data/lib/redis/subscribe.rb +23 -15
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +109 -3546
- metadata +27 -54
- data/lib/redis/cluster/command.rb +0 -81
- data/lib/redis/cluster/command_loader.rb +0 -34
- data/lib/redis/cluster/key_slot_converter.rb +0 -72
- data/lib/redis/cluster/node.rb +0 -108
- data/lib/redis/cluster/node_key.rb +0 -31
- data/lib/redis/cluster/node_loader.rb +0 -37
- data/lib/redis/cluster/option.rb +0 -93
- data/lib/redis/cluster/slot.rb +0 -86
- data/lib/redis/cluster/slot_loader.rb +0 -49
- data/lib/redis/cluster.rb +0 -291
- data/lib/redis/connection/command_helper.rb +0 -39
- data/lib/redis/connection/hiredis.rb +0 -67
- data/lib/redis/connection/registry.rb +0 -13
- data/lib/redis/connection/ruby.rb +0 -427
- data/lib/redis/connection/synchrony.rb +0 -146
- data/lib/redis/connection.rb +0 -11
data/lib/redis/distributed.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
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
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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(*
|
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(*
|
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,
|
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)
|
@@ -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
470
|
end
|
442
471
|
|
443
|
-
|
444
|
-
# Issue deprecation notice in obnoxious mode...
|
445
|
-
end
|
472
|
+
args.flatten!(1)
|
446
473
|
|
447
|
-
|
448
|
-
|
449
|
-
ensure_same_node(cmd, keys) do |node|
|
474
|
+
ensure_same_node(cmd, args) do |node|
|
450
475
|
if timeout
|
451
|
-
node.__send__(cmd,
|
476
|
+
node.__send__(cmd, args, timeout: timeout)
|
452
477
|
else
|
453
|
-
node.__send__(cmd,
|
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,
|
509
|
+
def brpoplpush(source, destination, **options)
|
473
510
|
ensure_same_node(:brpoplpush, [source, destination]) do |node|
|
474
|
-
node.brpoplpush(source, destination,
|
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,
|
515
|
-
node_for(key).sadd(key,
|
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,
|
520
|
-
node_for(key).srem(key,
|
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(
|
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
|
-
|
570
|
-
|
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(
|
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
|
-
|
584
|
-
|
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(
|
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
|
-
|
598
|
-
|
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
|
-
#
|
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)
|
@@ -676,26 +780,54 @@ class Redis
|
|
676
780
|
|
677
781
|
# Get the intersection of multiple sorted sets
|
678
782
|
def zinter(*keys, **options)
|
783
|
+
keys.flatten!(1)
|
679
784
|
ensure_same_node(:zinter, keys) do |node|
|
680
|
-
node.zinter(
|
785
|
+
node.zinter(keys, **options)
|
681
786
|
end
|
682
787
|
end
|
683
788
|
|
684
789
|
# Intersect multiple sorted sets and store the resulting sorted set in a new
|
685
790
|
# key.
|
686
|
-
def zinterstore(destination, keys, **options)
|
687
|
-
|
791
|
+
def zinterstore(destination, *keys, **options)
|
792
|
+
keys.flatten!(1)
|
793
|
+
ensure_same_node(:zinterstore, [destination].concat(keys)) do |node|
|
688
794
|
node.zinterstore(destination, keys, **options)
|
689
795
|
end
|
690
796
|
end
|
691
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
|
+
|
692
806
|
# Add multiple sorted sets and store the resulting sorted set in a new key.
|
693
|
-
def zunionstore(destination, keys, **options)
|
694
|
-
|
807
|
+
def zunionstore(destination, *keys, **options)
|
808
|
+
keys.flatten!(1)
|
809
|
+
ensure_same_node(:zunionstore, [destination].concat(keys)) do |node|
|
695
810
|
node.zunionstore(destination, keys, **options)
|
696
811
|
end
|
697
812
|
end
|
698
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
|
+
|
699
831
|
# Get the number of fields in a hash.
|
700
832
|
def hlen(key)
|
701
833
|
node_for(key).hlen(key)
|
@@ -717,7 +849,7 @@ class Redis
|
|
717
849
|
end
|
718
850
|
|
719
851
|
def mapped_hmset(key, hash)
|
720
|
-
node_for(key).hmset(key,
|
852
|
+
node_for(key).hmset(key, hash)
|
721
853
|
end
|
722
854
|
|
723
855
|
# Get the value of a hash field.
|
@@ -727,16 +859,23 @@ class Redis
|
|
727
859
|
|
728
860
|
# Get the values of all the given hash fields.
|
729
861
|
def hmget(key, *fields)
|
730
|
-
|
862
|
+
fields.flatten!(1)
|
863
|
+
node_for(key).hmget(key, fields)
|
731
864
|
end
|
732
865
|
|
733
866
|
def mapped_hmget(key, *fields)
|
734
|
-
|
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)
|
735
873
|
end
|
736
874
|
|
737
875
|
# Delete one or more hash fields.
|
738
876
|
def hdel(key, *fields)
|
739
|
-
|
877
|
+
fields.flatten!(1)
|
878
|
+
node_for(key).hdel(key, fields)
|
740
879
|
end
|
741
880
|
|
742
881
|
# Determine if a hash field exists.
|
@@ -793,7 +932,7 @@ class Redis
|
|
793
932
|
|
794
933
|
# Stop listening for messages posted to the given channels.
|
795
934
|
def unsubscribe(*channels)
|
796
|
-
raise "Can't unsubscribe if not subscribed." unless subscribed?
|
935
|
+
raise SubscriptionError, "Can't unsubscribe if not subscribed." unless subscribed?
|
797
936
|
|
798
937
|
@subscribed_node.unsubscribe(*channels)
|
799
938
|
end
|
@@ -840,9 +979,7 @@ class Redis
|
|
840
979
|
def multi(&block)
|
841
980
|
raise CannotDistribute, :multi unless @watch_key
|
842
981
|
|
843
|
-
|
844
|
-
@watch_key = nil if block_given?
|
845
|
-
result
|
982
|
+
node_for(@watch_key).multi(&block)
|
846
983
|
end
|
847
984
|
|
848
985
|
# Execute all commands issued after MULTI.
|
@@ -932,7 +1069,8 @@ class Redis
|
|
932
1069
|
end
|
933
1070
|
|
934
1071
|
def key_tag(key)
|
935
|
-
key.to_s
|
1072
|
+
key = key.to_s
|
1073
|
+
key[@tag, 1] if key.match?(@tag)
|
936
1074
|
end
|
937
1075
|
|
938
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 <
|
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
|
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
|