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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +190 -0
- data/README.md +132 -154
- data/lib/redis/client.rb +81 -600
- data/lib/redis/commands/bitmaps.rb +73 -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 +258 -0
- data/lib/redis/commands/hyper_log_log.rb +37 -0
- data/lib/redis/commands/keys.rb +459 -0
- data/lib/redis/commands/lists.rb +339 -0
- data/lib/redis/commands/pubsub.rb +81 -0
- data/lib/redis/commands/scripting.rb +114 -0
- data/lib/redis/commands/server.rb +188 -0
- data/lib/redis/commands/sets.rb +218 -0
- data/lib/redis/commands/sorted_sets.rb +922 -0
- data/lib/redis/commands/streams.rb +409 -0
- data/lib/redis/commands/strings.rb +314 -0
- data/lib/redis/commands/transactions.rb +115 -0
- data/lib/redis/commands.rb +239 -0
- data/lib/redis/distributed.rb +236 -77
- data/lib/redis/errors.rb +20 -41
- data/lib/redis/hash_ring.rb +26 -26
- data/lib/redis/pipeline.rb +70 -120
- data/lib/redis/subscribe.rb +50 -14
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +104 -3465
- metadata +27 -57
- 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 -107
- 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 -295
- 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,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
|
-
|
|
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
|
|
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(*
|
|
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(*
|
|
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,
|
|
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
|
-
|
|
482
|
+
args.flatten!(1)
|
|
448
483
|
|
|
449
|
-
ensure_same_node(cmd,
|
|
484
|
+
ensure_same_node(cmd, args) do |node|
|
|
450
485
|
if timeout
|
|
451
|
-
node.__send__(cmd,
|
|
486
|
+
node.__send__(cmd, args, timeout: timeout)
|
|
452
487
|
else
|
|
453
|
-
node.__send__(cmd,
|
|
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,
|
|
519
|
+
def brpoplpush(source, destination, **options)
|
|
473
520
|
ensure_same_node(:brpoplpush, [source, destination]) do |node|
|
|
474
|
-
node.brpoplpush(source, destination,
|
|
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,
|
|
515
|
-
node_for(key).sadd(key,
|
|
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,
|
|
520
|
-
node_for(key).srem(key,
|
|
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(
|
|
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
|
-
|
|
570
|
-
|
|
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(
|
|
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
|
-
|
|
584
|
-
|
|
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(
|
|
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
|
-
|
|
598
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
872
|
+
fields.flatten!(1)
|
|
873
|
+
node_for(key).hmget(key, fields)
|
|
724
874
|
end
|
|
725
875
|
|
|
726
876
|
def mapped_hmget(key, *fields)
|
|
727
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 <
|
|
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
|
|
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
|