redis 4.1.0 → 4.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +107 -0
- data/README.md +81 -17
- data/lib/redis/client.rb +137 -82
- data/lib/redis/cluster/command_loader.rb +6 -7
- data/lib/redis/cluster/node.rb +5 -1
- data/lib/redis/cluster/node_key.rb +3 -7
- data/lib/redis/cluster/option.rb +30 -14
- data/lib/redis/cluster/slot.rb +30 -13
- data/lib/redis/cluster/slot_loader.rb +4 -4
- data/lib/redis/cluster.rb +22 -17
- data/lib/redis/connection/command_helper.rb +5 -2
- data/lib/redis/connection/hiredis.rb +4 -3
- data/lib/redis/connection/registry.rb +2 -1
- data/lib/redis/connection/ruby.rb +121 -105
- data/lib/redis/connection/synchrony.rb +9 -4
- data/lib/redis/connection.rb +2 -0
- data/lib/redis/distributed.rb +170 -68
- data/lib/redis/errors.rb +2 -0
- data/lib/redis/hash_ring.rb +15 -14
- data/lib/redis/pipeline.rb +46 -8
- data/lib/redis/subscribe.rb +11 -12
- data/lib/redis/version.rb +3 -1
- data/lib/redis.rb +808 -476
- metadata +15 -25
data/lib/redis/pipeline.rb
CHANGED
@@ -1,15 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Redis
|
2
4
|
class Pipeline
|
3
5
|
attr_accessor :db
|
6
|
+
attr_reader :client
|
4
7
|
|
5
8
|
attr :futures
|
6
9
|
|
7
|
-
def initialize
|
10
|
+
def initialize(client)
|
11
|
+
@client = client.is_a?(Pipeline) ? client.client : client
|
8
12
|
@with_reconnect = true
|
9
13
|
@shutdown = false
|
10
14
|
@futures = []
|
11
15
|
end
|
12
16
|
|
17
|
+
def timeout
|
18
|
+
client.timeout
|
19
|
+
end
|
20
|
+
|
13
21
|
def with_reconnect?
|
14
22
|
@with_reconnect
|
15
23
|
end
|
@@ -26,15 +34,19 @@ class Redis
|
|
26
34
|
@futures.empty?
|
27
35
|
end
|
28
36
|
|
29
|
-
def call(command, &block)
|
37
|
+
def call(command, timeout: nil, &block)
|
30
38
|
# A pipeline that contains a shutdown should not raise ECONNRESET when
|
31
39
|
# the connection is gone.
|
32
40
|
@shutdown = true if command.first == :shutdown
|
33
|
-
future = Future.new(command, block)
|
41
|
+
future = Future.new(command, block, timeout)
|
34
42
|
@futures << future
|
35
43
|
future
|
36
44
|
end
|
37
45
|
|
46
|
+
def call_with_timeout(command, timeout, &block)
|
47
|
+
call(command, timeout: timeout, &block)
|
48
|
+
end
|
49
|
+
|
38
50
|
def call_pipeline(pipeline)
|
39
51
|
@shutdown = true if pipeline.shutdown?
|
40
52
|
@futures.concat(pipeline.futures)
|
@@ -43,10 +55,14 @@ class Redis
|
|
43
55
|
end
|
44
56
|
|
45
57
|
def commands
|
46
|
-
@futures.map
|
58
|
+
@futures.map(&:_command)
|
59
|
+
end
|
60
|
+
|
61
|
+
def timeouts
|
62
|
+
@futures.map(&:timeout)
|
47
63
|
end
|
48
64
|
|
49
|
-
def with_reconnect(val=true)
|
65
|
+
def with_reconnect(val = true)
|
50
66
|
@with_reconnect = false unless val
|
51
67
|
yield
|
52
68
|
end
|
@@ -78,7 +94,8 @@ class Redis
|
|
78
94
|
|
79
95
|
if exec.size < futures.size
|
80
96
|
# Some command wasn't recognized by Redis.
|
81
|
-
|
97
|
+
command_error = replies.detect { |r| r.is_a?(CommandError) }
|
98
|
+
raise command_error
|
82
99
|
end
|
83
100
|
|
84
101
|
super(exec) do |reply|
|
@@ -89,6 +106,14 @@ class Redis
|
|
89
106
|
end
|
90
107
|
end
|
91
108
|
|
109
|
+
def timeouts
|
110
|
+
if empty?
|
111
|
+
[]
|
112
|
+
else
|
113
|
+
[nil, *super, nil]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
92
117
|
def commands
|
93
118
|
if empty?
|
94
119
|
[]
|
@@ -108,12 +133,25 @@ class Redis
|
|
108
133
|
class Future < BasicObject
|
109
134
|
FutureNotReady = ::Redis::FutureNotReady.new
|
110
135
|
|
111
|
-
|
136
|
+
attr_reader :timeout
|
137
|
+
|
138
|
+
def initialize(command, transformation, timeout)
|
112
139
|
@command = command
|
113
140
|
@transformation = transformation
|
141
|
+
@timeout = timeout
|
114
142
|
@object = FutureNotReady
|
115
143
|
end
|
116
144
|
|
145
|
+
def ==(_other)
|
146
|
+
message = +"The methods == and != are deprecated for Redis::Future and will be removed in 4.2.0"
|
147
|
+
message << " - You probably meant to call .value == or .value !="
|
148
|
+
message << " (#{::Kernel.caller(1, 1).first})\n"
|
149
|
+
|
150
|
+
::Kernel.warn(message)
|
151
|
+
|
152
|
+
super
|
153
|
+
end
|
154
|
+
|
117
155
|
def inspect
|
118
156
|
"<Redis::Future #{@command.inspect}>"
|
119
157
|
end
|
@@ -128,7 +166,7 @@ class Redis
|
|
128
166
|
end
|
129
167
|
|
130
168
|
def value
|
131
|
-
::Kernel.raise(@object) if @object.
|
169
|
+
::Kernel.raise(@object) if @object.is_a?(::RuntimeError)
|
132
170
|
@object
|
133
171
|
end
|
134
172
|
|
data/lib/redis/subscribe.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Redis
|
2
4
|
class SubscribedClient
|
3
5
|
def initialize(client)
|
@@ -32,24 +34,21 @@ class Redis
|
|
32
34
|
call([:punsubscribe, *channels])
|
33
35
|
end
|
34
36
|
|
35
|
-
|
37
|
+
protected
|
36
38
|
|
37
39
|
def subscription(start, stop, channels, block, timeout = 0)
|
38
40
|
sub = Subscription.new(&block)
|
39
41
|
|
40
42
|
unsubscribed = false
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
break if unsubscribed
|
48
|
-
end
|
49
|
-
ensure
|
50
|
-
# No need to unsubscribe here. The real client closes the connection
|
51
|
-
# whenever an exception is raised (see #ensure_connected).
|
44
|
+
@client.call_loop([start, *channels], timeout) do |line|
|
45
|
+
type, *rest = line
|
46
|
+
sub.callbacks[type].call(*rest)
|
47
|
+
unsubscribed = type == stop && rest.last == 0
|
48
|
+
break if unsubscribed
|
52
49
|
end
|
50
|
+
# No need to unsubscribe here. The real client closes the connection
|
51
|
+
# whenever an exception is raised (see #ensure_connected).
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
@@ -58,7 +57,7 @@ class Redis
|
|
58
57
|
|
59
58
|
def initialize
|
60
59
|
@callbacks = Hash.new do |hash, key|
|
61
|
-
hash[key] =
|
60
|
+
hash[key] = ->(*_) {}
|
62
61
|
end
|
63
62
|
|
64
63
|
yield(self)
|
data/lib/redis/version.rb
CHANGED