redis 4.4.0 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/redis/client.rb +6 -2
- data/lib/redis/cluster/command_loader.rb +6 -7
- data/lib/redis/connection/command_helper.rb +2 -0
- data/lib/redis/connection/ruby.rb +24 -6
- data/lib/redis/distributed.rb +40 -0
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +194 -3
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1e483240f70aa8a92a7fe1f38968262ea82e84a97e436a9c7c695c032584313
|
4
|
+
data.tar.gz: 1cb164b2d588ef2f2701b91371a12a0d90299a78994f0d614cb14ab0daa36243
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72c3e91839061ae26e27cbb08330f752acbba5f440c8549cad4325b2c2f517a907a0db11330ca9ba221255aa7b570efe2050bde9cbb905217794c4754c53dadb
|
7
|
+
data.tar.gz: e92cc58111fb9e1553a3363c56569ef6064c3851263d5eb86147c907878650b697db5c598b2b2046f9c9025cc40ca7eda5ce16f4f21049ac49f09385cf80a92f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 4.5.0
|
4
|
+
|
5
|
+
* Handle parts of the command using incompatible encodings. See #1037.
|
6
|
+
* Add GET option to SET command. See #1036.
|
7
|
+
* Add ZRANDMEMBER command. See #1035.
|
8
|
+
* Add LMOVE/BLMOVE commands. See #1034.
|
9
|
+
* Add ZMSCORE command. See #1032.
|
10
|
+
* Add LT/GT options to ZADD. See #1033.
|
11
|
+
* Add SMISMEMBER command. See #1031.
|
12
|
+
* Add EXAT/PXAT options to SET. See #1028.
|
13
|
+
* Add GETDEL/GETEX commands. See #1024.
|
14
|
+
* `Redis#exists` now returns an Integer by default, as warned since 4.2.0. The old behavior can be restored with `Redis.exists_returns_integer = false`.
|
15
|
+
* Fix Redis < 6 detection during connect. See #1025.
|
16
|
+
* Fix fetching command details in Redis cluster when the first node is unhealthy. See #1026.
|
17
|
+
|
3
18
|
# 4.4.0
|
4
19
|
|
5
20
|
* Redis cluster: fix cross-slot validation in pipelines. Fix ##1019.
|
data/lib/redis/client.rb
CHANGED
@@ -119,8 +119,12 @@ class Redis
|
|
119
119
|
if username
|
120
120
|
begin
|
121
121
|
call [:auth, username, password]
|
122
|
-
rescue CommandError # Likely on Redis < 6
|
123
|
-
|
122
|
+
rescue CommandError => err # Likely on Redis < 6
|
123
|
+
if err.message.match?(/ERR wrong number of arguments for \'auth\' command/)
|
124
|
+
call [:auth, password]
|
125
|
+
else
|
126
|
+
raise
|
127
|
+
end
|
124
128
|
end
|
125
129
|
else
|
126
130
|
call [:auth, password]
|
@@ -10,22 +10,21 @@ class Redis
|
|
10
10
|
module_function
|
11
11
|
|
12
12
|
def load(nodes)
|
13
|
-
details = {}
|
14
|
-
|
15
13
|
nodes.each do |node|
|
16
|
-
|
17
|
-
|
14
|
+
begin
|
15
|
+
return fetch_command_details(node)
|
16
|
+
rescue CannotConnectError, ConnectionError, CommandError
|
17
|
+
next # can retry on another node
|
18
|
+
end
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
+
raise CannotConnectError, 'Redis client could not connect to any cluster nodes'
|
21
22
|
end
|
22
23
|
|
23
24
|
def fetch_command_details(node)
|
24
25
|
node.call(%i[command]).map do |reply|
|
25
26
|
[reply[0], { arity: reply[1], flags: reply[2], first: reply[3], last: reply[4], step: reply[5] }]
|
26
27
|
end.to_h
|
27
|
-
rescue CannotConnectError, ConnectionError, CommandError
|
28
|
-
{} # can retry on another node
|
29
28
|
end
|
30
29
|
|
31
30
|
private_class_method :fetch_command_details
|
@@ -12,11 +12,13 @@ class Redis
|
|
12
12
|
if i.is_a? Array
|
13
13
|
i.each do |j|
|
14
14
|
j = j.to_s
|
15
|
+
j = j.encoding == Encoding::BINARY ? j : j.b
|
15
16
|
command << "$#{j.bytesize}"
|
16
17
|
command << j
|
17
18
|
end
|
18
19
|
else
|
19
20
|
i = i.to_s
|
21
|
+
i = i.encoding == Encoding::BINARY ? i : i.b
|
20
22
|
command << "$#{i.bytesize}"
|
21
23
|
command << i
|
22
24
|
end
|
@@ -32,12 +32,30 @@ class Redis
|
|
32
32
|
@write_timeout = (timeout if timeout && timeout > 0)
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
string_capacity_support = begin
|
36
|
+
String.new(capacity: 0)
|
37
|
+
true # Ruby 2.4+
|
38
|
+
rescue ArgumentError
|
39
|
+
false # Ruby 2.3
|
40
|
+
end
|
41
|
+
|
42
|
+
if string_capacity_support
|
43
|
+
def read(nbytes)
|
44
|
+
result = @buffer.slice!(0, nbytes)
|
37
45
|
|
38
|
-
|
46
|
+
buffer = String.new(capacity: nbytes, encoding: Encoding::ASCII_8BIT)
|
47
|
+
result << _read_from_socket(nbytes - result.bytesize, buffer) while result.bytesize < nbytes
|
39
48
|
|
40
|
-
|
49
|
+
result
|
50
|
+
end
|
51
|
+
else
|
52
|
+
def read(nbytes)
|
53
|
+
result = @buffer.slice!(0, nbytes)
|
54
|
+
|
55
|
+
result << _read_from_socket(nbytes - result.bytesize, "".b) while result.bytesize < nbytes
|
56
|
+
|
57
|
+
result
|
58
|
+
end
|
41
59
|
end
|
42
60
|
|
43
61
|
def gets
|
@@ -48,9 +66,9 @@ class Redis
|
|
48
66
|
@buffer.slice!(0, crlf + CRLF.bytesize)
|
49
67
|
end
|
50
68
|
|
51
|
-
def _read_from_socket(nbytes)
|
69
|
+
def _read_from_socket(nbytes, buffer = nil)
|
52
70
|
loop do
|
53
|
-
case chunk = read_nonblock(nbytes, exception: false)
|
71
|
+
case chunk = read_nonblock(nbytes, buffer, exception: false)
|
54
72
|
when :wait_readable
|
55
73
|
unless wait_readable(@timeout)
|
56
74
|
raise Redis::TimeoutError
|
data/lib/redis/distributed.rb
CHANGED
@@ -316,6 +316,16 @@ class Redis
|
|
316
316
|
node_for(key).get(key)
|
317
317
|
end
|
318
318
|
|
319
|
+
# Get the value of a key and delete it.
|
320
|
+
def getdel(key)
|
321
|
+
node_for(key).getdel(key)
|
322
|
+
end
|
323
|
+
|
324
|
+
# Get the value of a key and sets its time to live based on options.
|
325
|
+
def getex(key, **options)
|
326
|
+
node_for(key).getex(key, **options)
|
327
|
+
end
|
328
|
+
|
319
329
|
# Get the values of all the given keys as an Array.
|
320
330
|
def mget(*keys)
|
321
331
|
mapped_mget(*keys).values_at(*keys)
|
@@ -393,6 +403,21 @@ class Redis
|
|
393
403
|
node_for(key).llen(key)
|
394
404
|
end
|
395
405
|
|
406
|
+
# Remove the first/last element in a list, append/prepend it to another list and return it.
|
407
|
+
def lmove(source, destination, where_source, where_destination)
|
408
|
+
ensure_same_node(:lmove, [source, destination]) do |node|
|
409
|
+
node.lmove(source, destination, where_source, where_destination)
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
# Remove the first/last element in a list and append/prepend it
|
414
|
+
# to another list and return it, or block until one is available.
|
415
|
+
def blmove(source, destination, where_source, where_destination, timeout: 0)
|
416
|
+
ensure_same_node(:lmove, [source, destination]) do |node|
|
417
|
+
node.blmove(source, destination, where_source, where_destination, timeout: timeout)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
396
421
|
# Prepend one or more values to a list.
|
397
422
|
def lpush(key, value)
|
398
423
|
node_for(key).lpush(key, value)
|
@@ -542,6 +567,11 @@ class Redis
|
|
542
567
|
node_for(key).sismember(key, member)
|
543
568
|
end
|
544
569
|
|
570
|
+
# Determine if multiple values are members of a set.
|
571
|
+
def smismember(key, *members)
|
572
|
+
node_for(key).smismember(key, *members)
|
573
|
+
end
|
574
|
+
|
545
575
|
# Get all the members in a set.
|
546
576
|
def smembers(key)
|
547
577
|
node_for(key).smembers(key)
|
@@ -626,6 +656,16 @@ class Redis
|
|
626
656
|
node_for(key).zscore(key, member)
|
627
657
|
end
|
628
658
|
|
659
|
+
# Get one or more random members from a sorted set.
|
660
|
+
def zrandmember(key, count = nil, **options)
|
661
|
+
node_for(key).zrandmember(key, count, **options)
|
662
|
+
end
|
663
|
+
|
664
|
+
# Get the scores associated with the given members in a sorted set.
|
665
|
+
def zmscore(key, *members)
|
666
|
+
node_for(key).zmscore(key, *members)
|
667
|
+
end
|
668
|
+
|
629
669
|
# Return a range of members in a sorted set, by index.
|
630
670
|
def zrange(key, start, stop, **options)
|
631
671
|
node_for(key).zrange(key, start, stop, **options)
|
data/lib/redis/version.rb
CHANGED
data/lib/redis.rb
CHANGED
@@ -4,6 +4,8 @@ require "monitor"
|
|
4
4
|
require_relative "redis/errors"
|
5
5
|
|
6
6
|
class Redis
|
7
|
+
@exists_returns_integer = true
|
8
|
+
|
7
9
|
class << self
|
8
10
|
attr_reader :exists_returns_integer
|
9
11
|
|
@@ -834,17 +836,23 @@ class Redis
|
|
834
836
|
# @param [Hash] options
|
835
837
|
# - `:ex => Integer`: Set the specified expire time, in seconds.
|
836
838
|
# - `:px => Integer`: Set the specified expire time, in milliseconds.
|
839
|
+
# - `:exat => Integer` : Set the specified Unix time at which the key will expire, in seconds.
|
840
|
+
# - `:pxat => Integer` : Set the specified Unix time at which the key will expire, in milliseconds.
|
837
841
|
# - `:nx => true`: Only set the key if it does not already exist.
|
838
842
|
# - `:xx => true`: Only set the key if it already exist.
|
839
843
|
# - `:keepttl => true`: Retain the time to live associated with the key.
|
844
|
+
# - `:get => true`: Return the old string stored at key, or nil if key did not exist.
|
840
845
|
# @return [String, Boolean] `"OK"` or true, false if `:nx => true` or `:xx => true`
|
841
|
-
def set(key, value, ex: nil, px: nil, nx: nil, xx: nil, keepttl: nil)
|
846
|
+
def set(key, value, ex: nil, px: nil, exat: nil, pxat: nil, nx: nil, xx: nil, keepttl: nil, get: nil)
|
842
847
|
args = [:set, key, value.to_s]
|
843
848
|
args << "EX" << ex if ex
|
844
849
|
args << "PX" << px if px
|
850
|
+
args << "EXAT" << exat if exat
|
851
|
+
args << "PXAT" << pxat if pxat
|
845
852
|
args << "NX" if nx
|
846
853
|
args << "XX" if xx
|
847
854
|
args << "KEEPTTL" if keepttl
|
855
|
+
args << "GET" if get
|
848
856
|
|
849
857
|
synchronize do |client|
|
850
858
|
if nx || xx
|
@@ -1110,6 +1118,45 @@ class Redis
|
|
1110
1118
|
end
|
1111
1119
|
end
|
1112
1120
|
|
1121
|
+
# Get the value of key and delete the key. This command is similar to GET,
|
1122
|
+
# except for the fact that it also deletes the key on success.
|
1123
|
+
#
|
1124
|
+
# @param [String] key
|
1125
|
+
# @return [String] the old value stored in the key, or `nil` if the key
|
1126
|
+
# did not exist
|
1127
|
+
def getdel(key)
|
1128
|
+
synchronize do |client|
|
1129
|
+
client.call([:getdel, key])
|
1130
|
+
end
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
# Get the value of key and optionally set its expiration. GETEX is similar to
|
1134
|
+
# GET, but is a write command with additional options. When no options are
|
1135
|
+
# provided, GETEX behaves like GET.
|
1136
|
+
#
|
1137
|
+
# @param [String] key
|
1138
|
+
# @param [Hash] options
|
1139
|
+
# - `:ex => Integer`: Set the specified expire time, in seconds.
|
1140
|
+
# - `:px => Integer`: Set the specified expire time, in milliseconds.
|
1141
|
+
# - `:exat => true`: Set the specified Unix time at which the key will
|
1142
|
+
# expire, in seconds.
|
1143
|
+
# - `:pxat => true`: Set the specified Unix time at which the key will
|
1144
|
+
# expire, in milliseconds.
|
1145
|
+
# - `:persist => true`: Remove the time to live associated with the key.
|
1146
|
+
# @return [String] The value of key, or nil when key does not exist.
|
1147
|
+
def getex(key, ex: nil, px: nil, exat: nil, pxat: nil, persist: false)
|
1148
|
+
args = [:getex, key]
|
1149
|
+
args << "EX" << ex if ex
|
1150
|
+
args << "PX" << px if px
|
1151
|
+
args << "EXAT" << exat if exat
|
1152
|
+
args << "PXAT" << pxat if pxat
|
1153
|
+
args << "PERSIST" if persist
|
1154
|
+
|
1155
|
+
synchronize do |client|
|
1156
|
+
client.call(args)
|
1157
|
+
end
|
1158
|
+
end
|
1159
|
+
|
1113
1160
|
# Get the length of the value stored in a key.
|
1114
1161
|
#
|
1115
1162
|
# @param [String] key
|
@@ -1131,6 +1178,59 @@ class Redis
|
|
1131
1178
|
end
|
1132
1179
|
end
|
1133
1180
|
|
1181
|
+
# Remove the first/last element in a list, append/prepend it to another list and return it.
|
1182
|
+
#
|
1183
|
+
# @param [String] source source key
|
1184
|
+
# @param [String] destination destination key
|
1185
|
+
# @param [String, Symbol] where_source from where to remove the element from the source list
|
1186
|
+
# e.g. 'LEFT' - from head, 'RIGHT' - from tail
|
1187
|
+
# @param [String, Symbol] where_destination where to push the element to the source list
|
1188
|
+
# e.g. 'LEFT' - to head, 'RIGHT' - to tail
|
1189
|
+
#
|
1190
|
+
# @return [nil, String] the element, or nil when the source key does not exist
|
1191
|
+
#
|
1192
|
+
# @note This command comes in place of the now deprecated RPOPLPUSH.
|
1193
|
+
# Doing LMOVE RIGHT LEFT is equivalent.
|
1194
|
+
def lmove(source, destination, where_source, where_destination)
|
1195
|
+
where_source, where_destination = _normalize_move_wheres(where_source, where_destination)
|
1196
|
+
|
1197
|
+
synchronize do |client|
|
1198
|
+
client.call([:lmove, source, destination, where_source, where_destination])
|
1199
|
+
end
|
1200
|
+
end
|
1201
|
+
|
1202
|
+
# Remove the first/last element in a list and append/prepend it
|
1203
|
+
# to another list and return it, or block until one is available.
|
1204
|
+
#
|
1205
|
+
# @example With timeout
|
1206
|
+
# element = redis.blmove("foo", "bar", "LEFT", "RIGHT", timeout: 5)
|
1207
|
+
# # => nil on timeout
|
1208
|
+
# # => "element" on success
|
1209
|
+
# @example Without timeout
|
1210
|
+
# element = redis.blmove("foo", "bar", "LEFT", "RIGHT")
|
1211
|
+
# # => "element"
|
1212
|
+
#
|
1213
|
+
# @param [String] source source key
|
1214
|
+
# @param [String] destination destination key
|
1215
|
+
# @param [String, Symbol] where_source from where to remove the element from the source list
|
1216
|
+
# e.g. 'LEFT' - from head, 'RIGHT' - from tail
|
1217
|
+
# @param [String, Symbol] where_destination where to push the element to the source list
|
1218
|
+
# e.g. 'LEFT' - to head, 'RIGHT' - to tail
|
1219
|
+
# @param [Hash] options
|
1220
|
+
# - `:timeout => Numeric`: timeout in seconds, defaults to no timeout
|
1221
|
+
#
|
1222
|
+
# @return [nil, String] the element, or nil when the source key does not exist or the timeout expired
|
1223
|
+
#
|
1224
|
+
def blmove(source, destination, where_source, where_destination, timeout: 0)
|
1225
|
+
where_source, where_destination = _normalize_move_wheres(where_source, where_destination)
|
1226
|
+
|
1227
|
+
synchronize do |client|
|
1228
|
+
command = [:blmove, source, destination, where_source, where_destination, timeout]
|
1229
|
+
timeout += client.timeout if timeout > 0
|
1230
|
+
client.call_with_timeout(command, timeout)
|
1231
|
+
end
|
1232
|
+
end
|
1233
|
+
|
1134
1234
|
# Prepend one or more values to a list, creating the list if it doesn't exist
|
1135
1235
|
#
|
1136
1236
|
# @param [String] key
|
@@ -1479,6 +1579,19 @@ class Redis
|
|
1479
1579
|
end
|
1480
1580
|
end
|
1481
1581
|
|
1582
|
+
# Determine if multiple values are members of a set.
|
1583
|
+
#
|
1584
|
+
# @param [String] key
|
1585
|
+
# @param [String, Array<String>] members
|
1586
|
+
# @return [Array<Boolean>]
|
1587
|
+
def smismember(key, *members)
|
1588
|
+
synchronize do |client|
|
1589
|
+
client.call([:smismember, key, *members]) do |reply|
|
1590
|
+
reply.map(&Boolify)
|
1591
|
+
end
|
1592
|
+
end
|
1593
|
+
end
|
1594
|
+
|
1482
1595
|
# Get all the members in a set.
|
1483
1596
|
#
|
1484
1597
|
# @param [String] key
|
@@ -1583,6 +1696,10 @@ class Redis
|
|
1583
1696
|
# add elements)
|
1584
1697
|
# - `:nx => true`: Don't update already existing elements (always
|
1585
1698
|
# add new elements)
|
1699
|
+
# - `:lt => true`: Only update existing elements if the new score
|
1700
|
+
# is less than the current score
|
1701
|
+
# - `:gt => true`: Only update existing elements if the new score
|
1702
|
+
# is greater than the current score
|
1586
1703
|
# - `:ch => true`: Modify the return value from the number of new
|
1587
1704
|
# elements added, to the total number of elements changed (CH is an
|
1588
1705
|
# abbreviation of changed); changed elements are new elements added
|
@@ -1597,10 +1714,12 @@ class Redis
|
|
1597
1714
|
# pairs that were **added** to the sorted set.
|
1598
1715
|
# - `Float` when option :incr is specified, holding the score of the member
|
1599
1716
|
# after incrementing it.
|
1600
|
-
def zadd(key, *args, nx: nil, xx: nil, ch: nil, incr: nil)
|
1717
|
+
def zadd(key, *args, nx: nil, xx: nil, lt: nil, gt: nil, ch: nil, incr: nil)
|
1601
1718
|
command = [:zadd, key]
|
1602
1719
|
command << "NX" if nx
|
1603
1720
|
command << "XX" if xx
|
1721
|
+
command << "LT" if lt
|
1722
|
+
command << "GT" if gt
|
1604
1723
|
command << "CH" if ch
|
1605
1724
|
command << "INCR" if incr
|
1606
1725
|
|
@@ -1763,6 +1882,63 @@ class Redis
|
|
1763
1882
|
end
|
1764
1883
|
end
|
1765
1884
|
|
1885
|
+
# Get the scores associated with the given members in a sorted set.
|
1886
|
+
#
|
1887
|
+
# @example Get the scores for members "a" and "b"
|
1888
|
+
# redis.zmscore("zset", "a", "b")
|
1889
|
+
# # => [32.0, 48.0]
|
1890
|
+
#
|
1891
|
+
# @param [String] key
|
1892
|
+
# @param [String, Array<String>] members
|
1893
|
+
# @return [Array<Float>] scores of the members
|
1894
|
+
def zmscore(key, *members)
|
1895
|
+
synchronize do |client|
|
1896
|
+
client.call([:zmscore, key, *members]) do |reply|
|
1897
|
+
reply.map(&Floatify)
|
1898
|
+
end
|
1899
|
+
end
|
1900
|
+
end
|
1901
|
+
|
1902
|
+
# Get one or more random members from a sorted set.
|
1903
|
+
#
|
1904
|
+
# @example Get one random member
|
1905
|
+
# redis.zrandmember("zset")
|
1906
|
+
# # => "a"
|
1907
|
+
# @example Get multiple random members
|
1908
|
+
# redis.zrandmember("zset", 2)
|
1909
|
+
# # => ["a", "b"]
|
1910
|
+
# @example Gem multiple random members with scores
|
1911
|
+
# redis.zrandmember("zset", 2, with_scores: true)
|
1912
|
+
# # => [["a", 2.0], ["b", 3.0]]
|
1913
|
+
#
|
1914
|
+
# @param [String] key
|
1915
|
+
# @param [Integer] count
|
1916
|
+
# @param [Hash] options
|
1917
|
+
# - `:with_scores => true`: include scores in output
|
1918
|
+
#
|
1919
|
+
# @return [nil, String, Array<String>, Array<[String, Float]>]
|
1920
|
+
# - when `key` does not exist or set is empty, `nil`
|
1921
|
+
# - when `count` is not specified, a member
|
1922
|
+
# - when `count` is specified and `:with_scores` is not specified, an array of members
|
1923
|
+
# - when `:with_scores` is specified, an array with `[member, score]` pairs
|
1924
|
+
def zrandmember(key, count = nil, withscores: false, with_scores: withscores)
|
1925
|
+
if with_scores && count.nil?
|
1926
|
+
raise ArgumentError, "count argument must be specified"
|
1927
|
+
end
|
1928
|
+
|
1929
|
+
args = [:zrandmember, key]
|
1930
|
+
args << count if count
|
1931
|
+
|
1932
|
+
if with_scores
|
1933
|
+
args << "WITHSCORES"
|
1934
|
+
block = FloatifyPairs
|
1935
|
+
end
|
1936
|
+
|
1937
|
+
synchronize do |client|
|
1938
|
+
client.call(args, &block)
|
1939
|
+
end
|
1940
|
+
end
|
1941
|
+
|
1766
1942
|
# Return a range of members in a sorted set, by index.
|
1767
1943
|
#
|
1768
1944
|
# @example Retrieve all members from a sorted set
|
@@ -3518,7 +3694,7 @@ class Redis
|
|
3518
3694
|
|
3519
3695
|
HashifyStreamEntries = lambda { |reply|
|
3520
3696
|
reply.compact.map do |entry_id, values|
|
3521
|
-
[entry_id, values
|
3697
|
+
[entry_id, values&.each_slice(2)&.to_h]
|
3522
3698
|
end
|
3523
3699
|
}
|
3524
3700
|
|
@@ -3635,6 +3811,21 @@ class Redis
|
|
3635
3811
|
end
|
3636
3812
|
end
|
3637
3813
|
end
|
3814
|
+
|
3815
|
+
def _normalize_move_wheres(where_source, where_destination)
|
3816
|
+
where_source = where_source.to_s.upcase
|
3817
|
+
where_destination = where_destination.to_s.upcase
|
3818
|
+
|
3819
|
+
if where_source != "LEFT" && where_source != "RIGHT"
|
3820
|
+
raise ArgumentError, "where_source must be 'LEFT' or 'RIGHT'"
|
3821
|
+
end
|
3822
|
+
|
3823
|
+
if where_destination != "LEFT" && where_destination != "RIGHT"
|
3824
|
+
raise ArgumentError, "where_destination must be 'LEFT' or 'RIGHT'"
|
3825
|
+
end
|
3826
|
+
|
3827
|
+
[where_source, where_destination]
|
3828
|
+
end
|
3638
3829
|
end
|
3639
3830
|
|
3640
3831
|
require_relative "redis/version"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Zygmuntowicz
|
@@ -16,7 +16,7 @@ authors:
|
|
16
16
|
autorequire:
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
|
-
date: 2021-
|
19
|
+
date: 2021-10-14 00:00:00.000000000 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: em-synchrony
|
@@ -102,9 +102,9 @@ licenses:
|
|
102
102
|
metadata:
|
103
103
|
bug_tracker_uri: https://github.com/redis/redis-rb/issues
|
104
104
|
changelog_uri: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md
|
105
|
-
documentation_uri: https://www.rubydoc.info/gems/redis/4.
|
105
|
+
documentation_uri: https://www.rubydoc.info/gems/redis/4.5.0
|
106
106
|
homepage_uri: https://github.com/redis/redis-rb
|
107
|
-
source_code_uri: https://github.com/redis/redis-rb/tree/v4.
|
107
|
+
source_code_uri: https://github.com/redis/redis-rb/tree/v4.5.0
|
108
108
|
post_install_message:
|
109
109
|
rdoc_options: []
|
110
110
|
require_paths:
|
@@ -113,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
113
|
requirements:
|
114
114
|
- - ">="
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version: 2.
|
116
|
+
version: 2.4.0
|
117
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
118
|
requirements:
|
119
119
|
- - ">="
|