redis 4.1.4 → 4.2.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 +19 -0
- data/README.md +8 -4
- data/lib/redis.rb +275 -237
- data/lib/redis/client.rb +66 -70
- data/lib/redis/cluster.rb +4 -0
- data/lib/redis/cluster/node.rb +3 -0
- data/lib/redis/cluster/option.rb +4 -1
- data/lib/redis/cluster/slot.rb +28 -14
- data/lib/redis/cluster/slot_loader.rb +2 -3
- data/lib/redis/connection.rb +1 -0
- data/lib/redis/connection/command_helper.rb +2 -2
- data/lib/redis/connection/hiredis.rb +3 -3
- data/lib/redis/connection/registry.rb +1 -1
- data/lib/redis/connection/ruby.rb +38 -61
- data/lib/redis/connection/synchrony.rb +8 -4
- data/lib/redis/distributed.rb +72 -50
- data/lib/redis/errors.rb +1 -0
- data/lib/redis/hash_ring.rb +14 -14
- data/lib/redis/pipeline.rb +6 -8
- data/lib/redis/subscribe.rb +10 -12
- data/lib/redis/version.rb +2 -1
- metadata +10 -5
data/lib/redis/connection.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
class Redis
|
3
4
|
module Connection
|
4
5
|
module CommandHelper
|
5
|
-
|
6
6
|
COMMAND_DELIMITER = "\r\n"
|
7
7
|
|
8
8
|
def build_command(args)
|
@@ -29,7 +29,7 @@ class Redis
|
|
29
29
|
command.join(COMMAND_DELIMITER)
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
protected
|
33
33
|
|
34
34
|
def encode(string)
|
35
35
|
string.force_encoding(Encoding.default_external)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative "registry"
|
3
4
|
require_relative "../errors"
|
4
5
|
require "hiredis/connection"
|
@@ -7,7 +8,6 @@ require "timeout"
|
|
7
8
|
class Redis
|
8
9
|
module Connection
|
9
10
|
class Hiredis
|
10
|
-
|
11
11
|
def self.connect(config)
|
12
12
|
connection = ::Hiredis::Connection.new
|
13
13
|
connect_timeout = (config.fetch(:connect_timeout, 0) * 1_000_000).to_i
|
@@ -32,7 +32,7 @@ class Redis
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def connected?
|
35
|
-
@connection
|
35
|
+
@connection&.connected?
|
36
36
|
end
|
37
37
|
|
38
38
|
def timeout=(timeout)
|
@@ -58,7 +58,7 @@ class Redis
|
|
58
58
|
rescue Errno::EAGAIN
|
59
59
|
raise TimeoutError
|
60
60
|
rescue RuntimeError => err
|
61
|
-
raise ProtocolError
|
61
|
+
raise ProtocolError, err.message
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
class Redis
|
3
4
|
module Connection
|
4
|
-
|
5
5
|
# Store a list of loaded connection drivers in the Connection module.
|
6
6
|
# Redis::Client uses the last required driver by default, and will be aware
|
7
7
|
# of the loaded connection drivers if the user chooses to override the
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative "registry"
|
3
4
|
require_relative "command_helper"
|
4
5
|
require_relative "../errors"
|
@@ -14,8 +15,7 @@ end
|
|
14
15
|
class Redis
|
15
16
|
module Connection
|
16
17
|
module SocketMixin
|
17
|
-
|
18
|
-
CRLF = "\r\n".freeze
|
18
|
+
CRLF = "\r\n"
|
19
19
|
|
20
20
|
def initialize(*args)
|
21
21
|
super(*args)
|
@@ -25,46 +25,32 @@ class Redis
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def timeout=(timeout)
|
28
|
-
if timeout && timeout > 0
|
29
|
-
@timeout = timeout
|
30
|
-
else
|
31
|
-
@timeout = nil
|
32
|
-
end
|
28
|
+
@timeout = (timeout if timeout && timeout > 0)
|
33
29
|
end
|
34
30
|
|
35
31
|
def write_timeout=(timeout)
|
36
|
-
if timeout && timeout > 0
|
37
|
-
@write_timeout = timeout
|
38
|
-
else
|
39
|
-
@write_timeout = nil
|
40
|
-
end
|
32
|
+
@write_timeout = (timeout if timeout && timeout > 0)
|
41
33
|
end
|
42
34
|
|
43
35
|
def read(nbytes)
|
44
36
|
result = @buffer.slice!(0, nbytes)
|
45
37
|
|
46
|
-
while result.bytesize < nbytes
|
47
|
-
result << _read_from_socket(nbytes - result.bytesize)
|
48
|
-
end
|
38
|
+
result << _read_from_socket(nbytes - result.bytesize) while result.bytesize < nbytes
|
49
39
|
|
50
40
|
result
|
51
41
|
end
|
52
42
|
|
53
43
|
def gets
|
54
|
-
crlf = nil
|
55
|
-
|
56
|
-
while (crlf = @buffer.index(CRLF)) == nil
|
57
|
-
@buffer << _read_from_socket(16384)
|
44
|
+
while (crlf = @buffer.index(CRLF)).nil?
|
45
|
+
@buffer << _read_from_socket(16_384)
|
58
46
|
end
|
59
47
|
|
60
48
|
@buffer.slice!(0, crlf + CRLF.bytesize)
|
61
49
|
end
|
62
50
|
|
63
51
|
def _read_from_socket(nbytes)
|
64
|
-
|
65
52
|
begin
|
66
53
|
read_nonblock(nbytes)
|
67
|
-
|
68
54
|
rescue IO::WaitReadable
|
69
55
|
if IO.select([self], nil, nil, @timeout)
|
70
56
|
retry
|
@@ -78,7 +64,6 @@ class Redis
|
|
78
64
|
raise Redis::TimeoutError
|
79
65
|
end
|
80
66
|
end
|
81
|
-
|
82
67
|
rescue EOFError
|
83
68
|
raise Errno::ECONNRESET
|
84
69
|
end
|
@@ -86,7 +71,6 @@ class Redis
|
|
86
71
|
def _write_to_socket(data)
|
87
72
|
begin
|
88
73
|
write_nonblock(data)
|
89
|
-
|
90
74
|
rescue IO::WaitWritable
|
91
75
|
if IO.select(nil, [self], nil, @write_timeout)
|
92
76
|
retry
|
@@ -100,7 +84,6 @@ class Redis
|
|
100
84
|
raise Redis::TimeoutError
|
101
85
|
end
|
102
86
|
end
|
103
|
-
|
104
87
|
rescue EOFError
|
105
88
|
raise Errno::ECONNRESET
|
106
89
|
end
|
@@ -115,6 +98,7 @@ class Redis
|
|
115
98
|
|
116
99
|
total_count += count
|
117
100
|
return total_count if total_count >= length
|
101
|
+
|
118
102
|
data = data.byteslice(count..-1)
|
119
103
|
end
|
120
104
|
end
|
@@ -125,7 +109,6 @@ class Redis
|
|
125
109
|
require "timeout"
|
126
110
|
|
127
111
|
class TCPSocket < ::TCPSocket
|
128
|
-
|
129
112
|
include SocketMixin
|
130
113
|
|
131
114
|
def self.connect(host, port, timeout)
|
@@ -141,7 +124,6 @@ class Redis
|
|
141
124
|
if defined?(::UNIXSocket)
|
142
125
|
|
143
126
|
class UNIXSocket < ::UNIXSocket
|
144
|
-
|
145
127
|
include SocketMixin
|
146
128
|
|
147
129
|
def self.connect(path, timeout)
|
@@ -159,7 +141,6 @@ class Redis
|
|
159
141
|
|
160
142
|
def _read_from_socket(nbytes)
|
161
143
|
readpartial(nbytes)
|
162
|
-
|
163
144
|
rescue EOFError
|
164
145
|
raise Errno::ECONNRESET
|
165
146
|
end
|
@@ -170,19 +151,16 @@ class Redis
|
|
170
151
|
else
|
171
152
|
|
172
153
|
class TCPSocket < ::Socket
|
173
|
-
|
174
154
|
include SocketMixin
|
175
155
|
|
176
|
-
def self.connect_addrinfo(
|
177
|
-
sock = new(::Socket.const_get(
|
178
|
-
sockaddr = ::Socket.pack_sockaddr_in(port,
|
156
|
+
def self.connect_addrinfo(addrinfo, port, timeout)
|
157
|
+
sock = new(::Socket.const_get(addrinfo[0]), Socket::SOCK_STREAM, 0)
|
158
|
+
sockaddr = ::Socket.pack_sockaddr_in(port, addrinfo[3])
|
179
159
|
|
180
160
|
begin
|
181
161
|
sock.connect_nonblock(sockaddr)
|
182
162
|
rescue Errno::EINPROGRESS
|
183
|
-
if IO.select(nil, [sock], nil, timeout)
|
184
|
-
raise TimeoutError
|
185
|
-
end
|
163
|
+
raise TimeoutError if IO.select(nil, [sock], nil, timeout).nil?
|
186
164
|
|
187
165
|
begin
|
188
166
|
sock.connect_nonblock(sockaddr)
|
@@ -221,14 +199,13 @@ class Redis
|
|
221
199
|
return connect_addrinfo(ai, port, timeout)
|
222
200
|
rescue SystemCallError
|
223
201
|
# Raise if this was our last attempt.
|
224
|
-
raise if addrinfo.length == i+1
|
202
|
+
raise if addrinfo.length == i + 1
|
225
203
|
end
|
226
204
|
end
|
227
205
|
end
|
228
206
|
end
|
229
207
|
|
230
208
|
class UNIXSocket < ::Socket
|
231
|
-
|
232
209
|
include SocketMixin
|
233
210
|
|
234
211
|
def self.connect(path, timeout)
|
@@ -238,9 +215,7 @@ class Redis
|
|
238
215
|
begin
|
239
216
|
sock.connect_nonblock(sockaddr)
|
240
217
|
rescue Errno::EINPROGRESS
|
241
|
-
if IO.select(nil, [sock], nil, timeout)
|
242
|
-
raise TimeoutError
|
243
|
-
end
|
218
|
+
raise TimeoutError if IO.select(nil, [sock], nil, timeout).nil?
|
244
219
|
|
245
220
|
begin
|
246
221
|
sock.connect_nonblock(sockaddr)
|
@@ -263,7 +238,9 @@ class Redis
|
|
263
238
|
tcp_sock = TCPSocket.connect(host, port, timeout)
|
264
239
|
|
265
240
|
ctx = OpenSSL::SSL::SSLContext.new
|
266
|
-
|
241
|
+
|
242
|
+
# The provided parameters are merged into OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
|
243
|
+
ctx.set_params(ssl_params || {})
|
267
244
|
|
268
245
|
ssl_sock = new(tcp_sock, ctx)
|
269
246
|
ssl_sock.hostname = host
|
@@ -290,7 +267,10 @@ class Redis
|
|
290
267
|
end
|
291
268
|
end
|
292
269
|
|
293
|
-
unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
|
270
|
+
unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
|
271
|
+
ctx.respond_to?(:verify_hostname) &&
|
272
|
+
!ctx.verify_hostname
|
273
|
+
)
|
294
274
|
ssl_sock.post_connection_check(host)
|
295
275
|
end
|
296
276
|
|
@@ -302,15 +282,16 @@ class Redis
|
|
302
282
|
class Ruby
|
303
283
|
include Redis::Connection::CommandHelper
|
304
284
|
|
305
|
-
MINUS = "-"
|
306
|
-
PLUS = "+"
|
307
|
-
COLON = ":"
|
308
|
-
DOLLAR = "$"
|
309
|
-
ASTERISK = "*"
|
285
|
+
MINUS = "-"
|
286
|
+
PLUS = "+"
|
287
|
+
COLON = ":"
|
288
|
+
DOLLAR = "$"
|
289
|
+
ASTERISK = "*"
|
310
290
|
|
311
291
|
def self.connect(config)
|
312
292
|
if config[:scheme] == "unix"
|
313
293
|
raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl]
|
294
|
+
|
314
295
|
sock = UNIXSocket.connect(config[:path], config[:connect_timeout])
|
315
296
|
elsif config[:scheme] == "rediss" || config[:ssl]
|
316
297
|
sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params])
|
@@ -326,7 +307,7 @@ class Redis
|
|
326
307
|
instance
|
327
308
|
end
|
328
309
|
|
329
|
-
if [
|
310
|
+
if %i[SOL_SOCKET SO_KEEPALIVE SOL_TCP TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT].all? { |c| Socket.const_defined? c }
|
330
311
|
def set_tcp_keepalive(keepalive)
|
331
312
|
return unless keepalive.is_a?(Hash)
|
332
313
|
|
@@ -338,14 +319,13 @@ class Redis
|
|
338
319
|
|
339
320
|
def get_tcp_keepalive
|
340
321
|
{
|
341
|
-
:
|
342
|
-
:
|
343
|
-
:
|
322
|
+
time: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
|
323
|
+
intvl: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
|
324
|
+
probes: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int
|
344
325
|
}
|
345
326
|
end
|
346
327
|
else
|
347
|
-
def set_tcp_keepalive(keepalive)
|
348
|
-
end
|
328
|
+
def set_tcp_keepalive(keepalive); end
|
349
329
|
|
350
330
|
def get_tcp_keepalive
|
351
331
|
{
|
@@ -354,13 +334,12 @@ class Redis
|
|
354
334
|
end
|
355
335
|
|
356
336
|
# disables Nagle's Algorithm, prevents multiple round trips with MULTI
|
357
|
-
if [
|
337
|
+
if %i[IPPROTO_TCP TCP_NODELAY].all? { |c| Socket.const_defined? c }
|
358
338
|
def set_tcp_nodelay
|
359
339
|
@sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
360
340
|
end
|
361
341
|
else
|
362
|
-
def set_tcp_nodelay
|
363
|
-
end
|
342
|
+
def set_tcp_nodelay; end
|
364
343
|
end
|
365
344
|
|
366
345
|
def initialize(sock)
|
@@ -368,7 +347,7 @@ class Redis
|
|
368
347
|
end
|
369
348
|
|
370
349
|
def connected?
|
371
|
-
|
350
|
+
!!@sock
|
372
351
|
end
|
373
352
|
|
374
353
|
def disconnect
|
@@ -379,9 +358,7 @@ class Redis
|
|
379
358
|
end
|
380
359
|
|
381
360
|
def timeout=(timeout)
|
382
|
-
if @sock.respond_to?(:timeout=)
|
383
|
-
@sock.timeout = timeout
|
384
|
-
end
|
361
|
+
@sock.timeout = timeout if @sock.respond_to?(:timeout=)
|
385
362
|
end
|
386
363
|
|
387
364
|
def write_timeout=(timeout)
|
@@ -396,7 +373,6 @@ class Redis
|
|
396
373
|
line = @sock.gets
|
397
374
|
reply_type = line.slice!(0, 1)
|
398
375
|
format_reply(reply_type, line)
|
399
|
-
|
400
376
|
rescue Errno::EAGAIN
|
401
377
|
raise TimeoutError
|
402
378
|
end
|
@@ -408,7 +384,7 @@ class Redis
|
|
408
384
|
when COLON then format_integer_reply(line)
|
409
385
|
when DOLLAR then format_bulk_reply(line)
|
410
386
|
when ASTERISK then format_multi_bulk_reply(line)
|
411
|
-
else raise ProtocolError
|
387
|
+
else raise ProtocolError, reply_type
|
412
388
|
end
|
413
389
|
end
|
414
390
|
|
@@ -427,6 +403,7 @@ class Redis
|
|
427
403
|
def format_bulk_reply(line)
|
428
404
|
bulklen = line.to_i
|
429
405
|
return if bulklen == -1
|
406
|
+
|
430
407
|
reply = encode(@sock.read(bulklen))
|
431
408
|
@sock.read(2) # Discard CRLF.
|
432
409
|
reply
|
@@ -1,10 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative "command_helper"
|
3
4
|
require_relative "registry"
|
4
5
|
require_relative "../errors"
|
5
6
|
require "em-synchrony"
|
6
7
|
require "hiredis/reader"
|
7
8
|
|
9
|
+
Kernel.warn(
|
10
|
+
"The redis synchrony driver is deprecated and will be removed in redis-rb 5.0. " \
|
11
|
+
"We're looking for people to maintain it as a separate gem, see https://github.com/redis/redis-rb/issues/915"
|
12
|
+
)
|
13
|
+
|
8
14
|
class Redis
|
9
15
|
module Connection
|
10
16
|
class RedisClient < EventMachine::Connection
|
@@ -47,9 +53,7 @@ class Redis
|
|
47
53
|
|
48
54
|
def read
|
49
55
|
@req = EventMachine::DefaultDeferrable.new
|
50
|
-
if @timeout > 0
|
51
|
-
@req.timeout(@timeout, :timeout)
|
52
|
-
end
|
56
|
+
@req.timeout(@timeout, :timeout) if @timeout > 0
|
53
57
|
EventMachine::Synchrony.sync @req
|
54
58
|
end
|
55
59
|
|
@@ -106,7 +110,7 @@ class Redis
|
|
106
110
|
end
|
107
111
|
|
108
112
|
def connected?
|
109
|
-
@connection
|
113
|
+
@connection&.connected?
|
110
114
|
end
|
111
115
|
|
112
116
|
def timeout=(timeout)
|
data/lib/redis/distributed.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative "hash_ring"
|
3
4
|
|
4
5
|
class Redis
|
5
6
|
class Distributed
|
6
|
-
|
7
7
|
class CannotDistribute < RuntimeError
|
8
8
|
def initialize(command)
|
9
9
|
@command = command
|
10
10
|
end
|
11
11
|
|
12
12
|
def message
|
13
|
-
"#{@command.to_s.upcase} cannot be used in Redis::Distributed because the keys involved need
|
13
|
+
"#{@command.to_s.upcase} cannot be used in Redis::Distributed because the keys involved need " \
|
14
|
+
"to be on the same server or because we cannot guarantee that the operation will be atomic."
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -34,9 +35,9 @@ class Redis
|
|
34
35
|
end
|
35
36
|
|
36
37
|
def add_node(options)
|
37
|
-
options = { :
|
38
|
+
options = { url: options } if options.is_a?(String)
|
38
39
|
options = @default_options.merge(options)
|
39
|
-
@ring.add_node Redis.new(
|
40
|
+
@ring.add_node Redis.new(options)
|
40
41
|
end
|
41
42
|
|
42
43
|
# Change the selected database for the current connection.
|
@@ -145,12 +146,12 @@ class Redis
|
|
145
146
|
end
|
146
147
|
|
147
148
|
# Create a key using the serialized value, previously obtained using DUMP.
|
148
|
-
def restore(key, ttl, serialized_value, options
|
149
|
-
node_for(key).restore(key, ttl, serialized_value, options)
|
149
|
+
def restore(key, ttl, serialized_value, **options)
|
150
|
+
node_for(key).restore(key, ttl, serialized_value, **options)
|
150
151
|
end
|
151
152
|
|
152
153
|
# Transfer a key from the connected instance to another instance.
|
153
|
-
def migrate(
|
154
|
+
def migrate(_key, _options)
|
154
155
|
raise CannotDistribute, :migrate
|
155
156
|
end
|
156
157
|
|
@@ -171,8 +172,33 @@ class Redis
|
|
171
172
|
end
|
172
173
|
|
173
174
|
# Determine if a key exists.
|
174
|
-
def exists(
|
175
|
-
|
175
|
+
def exists(*args)
|
176
|
+
if !Redis.exists_returns_integer && args.size == 1
|
177
|
+
message = "`Redis#exists(key)` will return an Integer in redis-rb 4.3, if you want to keep the old behavior, " \
|
178
|
+
"use `exists?` instead. To opt-in to the new behavior now you can set Redis.exists_returns_integer = true. " \
|
179
|
+
"(#{::Kernel.caller(1, 1).first})\n"
|
180
|
+
|
181
|
+
if defined?(::Warning)
|
182
|
+
::Warning.warn(message)
|
183
|
+
else
|
184
|
+
warn(message)
|
185
|
+
end
|
186
|
+
exists?(*args)
|
187
|
+
else
|
188
|
+
keys_per_node = args.group_by { |key| node_for(key) }
|
189
|
+
keys_per_node.inject(0) do |sum, (node, keys)|
|
190
|
+
sum + node._exists(*keys)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Determine if any of the keys exists.
|
196
|
+
def exists?(*args)
|
197
|
+
keys_per_node = args.group_by { |key| node_for(key) }
|
198
|
+
keys_per_node.each do |node, keys|
|
199
|
+
return true if node.exists?(*keys)
|
200
|
+
end
|
201
|
+
false
|
176
202
|
end
|
177
203
|
|
178
204
|
# Find all keys matching the given pattern.
|
@@ -205,11 +231,11 @@ class Redis
|
|
205
231
|
end
|
206
232
|
|
207
233
|
# Sort the elements in a list, set or sorted set.
|
208
|
-
def sort(key, options
|
234
|
+
def sort(key, **options)
|
209
235
|
keys = [key, options[:by], options[:store], *Array(options[:get])].compact
|
210
236
|
|
211
237
|
ensure_same_node(:sort, keys) do |node|
|
212
|
-
node.sort(key, options)
|
238
|
+
node.sort(key, **options)
|
213
239
|
end
|
214
240
|
end
|
215
241
|
|
@@ -244,8 +270,8 @@ class Redis
|
|
244
270
|
end
|
245
271
|
|
246
272
|
# Set the string value of a key.
|
247
|
-
def set(key, value, options
|
248
|
-
node_for(key).set(key, value, options)
|
273
|
+
def set(key, value, **options)
|
274
|
+
node_for(key).set(key, value, **options)
|
249
275
|
end
|
250
276
|
|
251
277
|
# Set the time to live in seconds of a key.
|
@@ -264,20 +290,20 @@ class Redis
|
|
264
290
|
end
|
265
291
|
|
266
292
|
# Set multiple keys to multiple values.
|
267
|
-
def mset(*
|
293
|
+
def mset(*_args)
|
268
294
|
raise CannotDistribute, :mset
|
269
295
|
end
|
270
296
|
|
271
|
-
def mapped_mset(
|
297
|
+
def mapped_mset(_hash)
|
272
298
|
raise CannotDistribute, :mapped_mset
|
273
299
|
end
|
274
300
|
|
275
301
|
# Set multiple keys to multiple values, only if none of the keys exist.
|
276
|
-
def msetnx(*
|
302
|
+
def msetnx(*_args)
|
277
303
|
raise CannotDistribute, :msetnx
|
278
304
|
end
|
279
305
|
|
280
|
-
def mapped_msetnx(
|
306
|
+
def mapped_msetnx(_hash)
|
281
307
|
raise CannotDistribute, :mapped_msetnx
|
282
308
|
end
|
283
309
|
|
@@ -336,7 +362,7 @@ class Redis
|
|
336
362
|
end
|
337
363
|
|
338
364
|
# Return the position of the first bit set to 1 or 0 in a string.
|
339
|
-
def bitpos(key, bit, start=nil, stop=nil)
|
365
|
+
def bitpos(key, bit, start = nil, stop = nil)
|
340
366
|
node_for(key).bitpos(key, bit, start, stop)
|
341
367
|
end
|
342
368
|
|
@@ -354,7 +380,7 @@ class Redis
|
|
354
380
|
get(key)
|
355
381
|
end
|
356
382
|
|
357
|
-
def []=(key,value)
|
383
|
+
def []=(key, value)
|
358
384
|
set(key, value)
|
359
385
|
end
|
360
386
|
|
@@ -439,15 +465,9 @@ class Redis
|
|
439
465
|
|
440
466
|
# Pop a value from a list, push it to another list and return it; or block
|
441
467
|
# until one is available.
|
442
|
-
def brpoplpush(source, destination,
|
443
|
-
case options
|
444
|
-
when Integer
|
445
|
-
# Issue deprecation notice in obnoxious mode...
|
446
|
-
options = { :timeout => options }
|
447
|
-
end
|
448
|
-
|
468
|
+
def brpoplpush(source, destination, deprecated_timeout = 0, **options)
|
449
469
|
ensure_same_node(:brpoplpush, [source, destination]) do |node|
|
450
|
-
node.brpoplpush(source, destination, options)
|
470
|
+
node.brpoplpush(source, destination, deprecated_timeout, **options)
|
451
471
|
end
|
452
472
|
end
|
453
473
|
|
@@ -524,13 +544,13 @@ class Redis
|
|
524
544
|
end
|
525
545
|
|
526
546
|
# Scan a set
|
527
|
-
def sscan(key, cursor, options
|
528
|
-
node_for(key).sscan(key, cursor, options)
|
547
|
+
def sscan(key, cursor, **options)
|
548
|
+
node_for(key).sscan(key, cursor, **options)
|
529
549
|
end
|
530
550
|
|
531
551
|
# Scan a set and return an enumerator
|
532
|
-
def sscan_each(key, options
|
533
|
-
node_for(key).sscan_each(key, options, &block)
|
552
|
+
def sscan_each(key, **options, &block)
|
553
|
+
node_for(key).sscan_each(key, **options, &block)
|
534
554
|
end
|
535
555
|
|
536
556
|
# Subtract multiple sets.
|
@@ -585,6 +605,7 @@ class Redis
|
|
585
605
|
def zadd(key, *args)
|
586
606
|
node_for(key).zadd(key, *args)
|
587
607
|
end
|
608
|
+
ruby2_keywords(:zadd) if respond_to?(:ruby2_keywords, true)
|
588
609
|
|
589
610
|
# Increment the score of a member in a sorted set.
|
590
611
|
def zincrby(key, increment, member)
|
@@ -602,14 +623,14 @@ class Redis
|
|
602
623
|
end
|
603
624
|
|
604
625
|
# Return a range of members in a sorted set, by index.
|
605
|
-
def zrange(key, start, stop, options
|
606
|
-
node_for(key).zrange(key, start, stop, options)
|
626
|
+
def zrange(key, start, stop, **options)
|
627
|
+
node_for(key).zrange(key, start, stop, **options)
|
607
628
|
end
|
608
629
|
|
609
630
|
# Return a range of members in a sorted set, by index, with scores ordered
|
610
631
|
# from high to low.
|
611
|
-
def zrevrange(key, start, stop, options
|
612
|
-
node_for(key).zrevrange(key, start, stop, options)
|
632
|
+
def zrevrange(key, start, stop, **options)
|
633
|
+
node_for(key).zrevrange(key, start, stop, **options)
|
613
634
|
end
|
614
635
|
|
615
636
|
# Determine the index of a member in a sorted set.
|
@@ -629,14 +650,14 @@ class Redis
|
|
629
650
|
end
|
630
651
|
|
631
652
|
# Return a range of members in a sorted set, by score.
|
632
|
-
def zrangebyscore(key, min, max, options
|
633
|
-
node_for(key).zrangebyscore(key, min, max, options)
|
653
|
+
def zrangebyscore(key, min, max, **options)
|
654
|
+
node_for(key).zrangebyscore(key, min, max, **options)
|
634
655
|
end
|
635
656
|
|
636
657
|
# Return a range of members in a sorted set, by score, with scores ordered
|
637
658
|
# from high to low.
|
638
|
-
def zrevrangebyscore(key, max, min, options
|
639
|
-
node_for(key).zrevrangebyscore(key, max, min, options)
|
659
|
+
def zrevrangebyscore(key, max, min, **options)
|
660
|
+
node_for(key).zrevrangebyscore(key, max, min, **options)
|
640
661
|
end
|
641
662
|
|
642
663
|
# Remove all members in a sorted set within the given scores.
|
@@ -651,16 +672,16 @@ class Redis
|
|
651
672
|
|
652
673
|
# Intersect multiple sorted sets and store the resulting sorted set in a new
|
653
674
|
# key.
|
654
|
-
def zinterstore(destination, keys, options
|
675
|
+
def zinterstore(destination, keys, **options)
|
655
676
|
ensure_same_node(:zinterstore, [destination] + keys) do |node|
|
656
|
-
node.zinterstore(destination, keys, options)
|
677
|
+
node.zinterstore(destination, keys, **options)
|
657
678
|
end
|
658
679
|
end
|
659
680
|
|
660
681
|
# Add multiple sorted sets and store the resulting sorted set in a new key.
|
661
|
-
def zunionstore(destination, keys, options
|
682
|
+
def zunionstore(destination, keys, **options)
|
662
683
|
ensure_same_node(:zunionstore, [destination] + keys) do |node|
|
663
|
-
node.zunionstore(destination, keys, options)
|
684
|
+
node.zunionstore(destination, keys, **options)
|
664
685
|
end
|
665
686
|
end
|
666
687
|
|
@@ -669,9 +690,9 @@ class Redis
|
|
669
690
|
node_for(key).hlen(key)
|
670
691
|
end
|
671
692
|
|
672
|
-
# Set
|
673
|
-
def hset(key,
|
674
|
-
node_for(key).hset(key,
|
693
|
+
# Set multiple hash fields to multiple values.
|
694
|
+
def hset(key, *attrs)
|
695
|
+
node_for(key).hset(key, *attrs)
|
675
696
|
end
|
676
697
|
|
677
698
|
# Set the value of a hash field, only if the field does not exist.
|
@@ -743,7 +764,7 @@ class Redis
|
|
743
764
|
end
|
744
765
|
|
745
766
|
def subscribed?
|
746
|
-
|
767
|
+
!!@subscribed_node
|
747
768
|
end
|
748
769
|
|
749
770
|
# Listen for messages published to the given channels.
|
@@ -761,7 +782,8 @@ class Redis
|
|
761
782
|
|
762
783
|
# Stop listening for messages posted to the given channels.
|
763
784
|
def unsubscribe(*channels)
|
764
|
-
raise
|
785
|
+
raise "Can't unsubscribe if not subscribed." unless subscribed?
|
786
|
+
|
765
787
|
@subscribed_node.unsubscribe(*channels)
|
766
788
|
end
|
767
789
|
|
@@ -777,7 +799,7 @@ class Redis
|
|
777
799
|
end
|
778
800
|
|
779
801
|
# Watch the given keys to determine execution of the MULTI/EXEC block.
|
780
|
-
def watch(*
|
802
|
+
def watch(*_keys)
|
781
803
|
raise CannotDistribute, :watch
|
782
804
|
end
|
783
805
|
|
@@ -861,7 +883,7 @@ class Redis
|
|
861
883
|
self.class.new(@node_configs, @default_options)
|
862
884
|
end
|
863
885
|
|
864
|
-
|
886
|
+
protected
|
865
887
|
|
866
888
|
def on_each_node(command, *args)
|
867
889
|
nodes.map do |node|
|