redis 4.2.2 → 4.3.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 +23 -0
- data/README.md +17 -11
- data/lib/redis.rb +40 -24
- data/lib/redis/client.rb +26 -4
- data/lib/redis/cluster.rb +1 -1
- data/lib/redis/cluster/option.rb +5 -2
- data/lib/redis/connection/ruby.rb +53 -48
- data/lib/redis/distributed.rb +6 -6
- data/lib/redis/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 416a2f007042c19453c13361aa4440a507e47fb32c28adc68e7c574c6651f5b4
|
|
4
|
+
data.tar.gz: 1a845f2af649d64f8b274962c9d5d10e6eb5d046474b6e44288676432fe8a98b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3766992242ae284ca474bc8564c6760de88e635a8c3bc3c80da08062d698cc891bf00455b5d98768709ecc766f8ad305fe03cc5806f03fda3ebb93049e0a1cce
|
|
7
|
+
data.tar.gz: f440c984ec58ff091a6a696952239cb04cf145752b485543e5da7215a327b40be4391b3fe6ca67753f84ec43913b9d90ec0b6f812e1696890a7c17cbf3aa3630
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Unreleased
|
|
2
2
|
|
|
3
|
+
# 4.3.1
|
|
4
|
+
|
|
5
|
+
* Fix password authentication against redis server 5 and older.
|
|
6
|
+
|
|
7
|
+
# 4.3.0
|
|
8
|
+
|
|
9
|
+
* Add the TYPE argument to scan and scan_each. See #985.
|
|
10
|
+
* Support AUTH command for ACL. See #967.
|
|
11
|
+
|
|
12
|
+
# 4.2.5
|
|
13
|
+
|
|
14
|
+
* Optimize the ruby connector write buffering. See #964.
|
|
15
|
+
|
|
16
|
+
# 4.2.4
|
|
17
|
+
|
|
18
|
+
* Fix bytesize calculations in the ruby connector, and work on a copy of the buffer. Fix #961, #962.
|
|
19
|
+
|
|
20
|
+
# 4.2.3
|
|
21
|
+
|
|
22
|
+
* Use io/wait instead of IO.select in the ruby connector. See #960.
|
|
23
|
+
* Use exception free non blocking IOs in the ruby connector. See #926.
|
|
24
|
+
* Prevent corruption of the client when an interrupt happen during inside a pipeline block. See #945.
|
|
25
|
+
|
|
3
26
|
# 4.2.2
|
|
4
27
|
|
|
5
28
|
* Fix `WATCH` support for `Redis::Distributed`. See #941.
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# redis-rb [![Build Status][
|
|
1
|
+
# redis-rb [![Build Status][gh-actions-image]][gh-actions-link] [![Inline docs][inchpages-image]][inchpages-link]
|
|
2
2
|
|
|
3
3
|
A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still
|
|
4
4
|
providing an idiomatic interface.
|
|
@@ -54,6 +54,12 @@ To connect to a password protected Redis instance, use:
|
|
|
54
54
|
redis = Redis.new(password: "mysecret")
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
To connect a Redis instance using [ACL](https://redis.io/topics/acl), use:
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
redis = Redis.new(username: 'myname', password: 'mysecret')
|
|
61
|
+
```
|
|
62
|
+
|
|
57
63
|
The Redis class exports methods that are named identical to the commands
|
|
58
64
|
they execute. The arguments these methods accept are often identical to
|
|
59
65
|
the arguments specified on the [Redis website][redis-commands]. For
|
|
@@ -265,6 +271,7 @@ All timeout values are specified in seconds.
|
|
|
265
271
|
When using pub/sub, you can subscribe to a channel using a timeout as well:
|
|
266
272
|
|
|
267
273
|
```ruby
|
|
274
|
+
redis = Redis.new(reconnect_attempts: 0)
|
|
268
275
|
redis.subscribe_with_timeout(5, "news") do |on|
|
|
269
276
|
on.message do |channel, message|
|
|
270
277
|
# ...
|
|
@@ -439,7 +446,7 @@ redis = Redis.new(:driver => :synchrony)
|
|
|
439
446
|
## Testing
|
|
440
447
|
|
|
441
448
|
This library is tested against recent Ruby and Redis versions.
|
|
442
|
-
Check [
|
|
449
|
+
Check [Github Actions][gh-actions-link] for the exact versions supported.
|
|
443
450
|
|
|
444
451
|
## See Also
|
|
445
452
|
|
|
@@ -458,12 +465,11 @@ client and evangelized Redis in Rubyland. Thank you, Ezra.
|
|
|
458
465
|
requests.
|
|
459
466
|
|
|
460
467
|
|
|
461
|
-
[inchpages-image]:
|
|
462
|
-
[inchpages-link]:
|
|
463
|
-
[redis-commands]:
|
|
464
|
-
[redis-home]:
|
|
465
|
-
[redis-url]:
|
|
466
|
-
[
|
|
467
|
-
[
|
|
468
|
-
[
|
|
469
|
-
[rubydoc]: http://www.rubydoc.info/gems/redis
|
|
468
|
+
[inchpages-image]: https://inch-ci.org/github/redis/redis-rb.svg
|
|
469
|
+
[inchpages-link]: https://inch-ci.org/github/redis/redis-rb
|
|
470
|
+
[redis-commands]: https://redis.io/commands
|
|
471
|
+
[redis-home]: https://redis.io
|
|
472
|
+
[redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis
|
|
473
|
+
[gh-actions-image]: https://github.com/redis/redis-rb/workflows/Test/badge.svg
|
|
474
|
+
[gh-actions-link]: https://github.com/redis/redis-rb/actions
|
|
475
|
+
[rubydoc]: http://www.rubydoc.info/gems/redis
|
data/lib/redis.rb
CHANGED
|
@@ -39,6 +39,7 @@ class Redis
|
|
|
39
39
|
# @option options [String] :path path to server socket (overrides host and port)
|
|
40
40
|
# @option options [Float] :timeout (5.0) timeout in seconds
|
|
41
41
|
# @option options [Float] :connect_timeout (same as timeout) timeout for initial connect in seconds
|
|
42
|
+
# @option options [String] :username Username to authenticate against server
|
|
42
43
|
# @option options [String] :password Password to authenticate against server
|
|
43
44
|
# @option options [Integer] :db (0) Database to select after initial connect
|
|
44
45
|
# @option options [Symbol] :driver Driver to use, currently supported: `:ruby`, `:hiredis`, `:synchrony`
|
|
@@ -143,12 +144,13 @@ class Redis
|
|
|
143
144
|
|
|
144
145
|
# Authenticate to the server.
|
|
145
146
|
#
|
|
146
|
-
# @param [String]
|
|
147
|
-
#
|
|
147
|
+
# @param [Array<String>] args includes both username and password
|
|
148
|
+
# or only password
|
|
148
149
|
# @return [String] `OK`
|
|
149
|
-
|
|
150
|
+
# @see https://redis.io/commands/auth AUTH command
|
|
151
|
+
def auth(*args)
|
|
150
152
|
synchronize do |client|
|
|
151
|
-
client.call([:auth,
|
|
153
|
+
client.call([:auth, *args])
|
|
152
154
|
end
|
|
153
155
|
end
|
|
154
156
|
|
|
@@ -1170,23 +1172,29 @@ class Redis
|
|
|
1170
1172
|
end
|
|
1171
1173
|
end
|
|
1172
1174
|
|
|
1173
|
-
# Remove and get the first
|
|
1175
|
+
# Remove and get the first elements in a list.
|
|
1174
1176
|
#
|
|
1175
1177
|
# @param [String] key
|
|
1176
|
-
# @
|
|
1177
|
-
|
|
1178
|
+
# @param [Integer] count number of elements to remove
|
|
1179
|
+
# @return [String, Array<String>] the values of the first elements
|
|
1180
|
+
def lpop(key, count = nil)
|
|
1178
1181
|
synchronize do |client|
|
|
1179
|
-
|
|
1182
|
+
command = [:lpop, key]
|
|
1183
|
+
command << count if count
|
|
1184
|
+
client.call(command)
|
|
1180
1185
|
end
|
|
1181
1186
|
end
|
|
1182
1187
|
|
|
1183
|
-
# Remove and get the last
|
|
1188
|
+
# Remove and get the last elements in a list.
|
|
1184
1189
|
#
|
|
1185
1190
|
# @param [String] key
|
|
1186
|
-
# @
|
|
1187
|
-
|
|
1191
|
+
# @param [Integer] count number of elements to remove
|
|
1192
|
+
# @return [String, Array<String>] the values of the last elements
|
|
1193
|
+
def rpop(key, count = nil)
|
|
1188
1194
|
synchronize do |client|
|
|
1189
|
-
|
|
1195
|
+
command = [:rpop, key]
|
|
1196
|
+
command << count if count
|
|
1197
|
+
client.call(command)
|
|
1190
1198
|
end
|
|
1191
1199
|
end
|
|
1192
1200
|
|
|
@@ -2438,14 +2446,13 @@ class Redis
|
|
|
2438
2446
|
end
|
|
2439
2447
|
|
|
2440
2448
|
def pipelined
|
|
2441
|
-
synchronize do |
|
|
2449
|
+
synchronize do |prior_client|
|
|
2442
2450
|
begin
|
|
2443
|
-
|
|
2444
|
-
original, @client = @client, pipeline
|
|
2451
|
+
@client = Pipeline.new(prior_client)
|
|
2445
2452
|
yield(self)
|
|
2446
|
-
|
|
2453
|
+
prior_client.call_pipeline(@client)
|
|
2447
2454
|
ensure
|
|
2448
|
-
@client =
|
|
2455
|
+
@client = prior_client
|
|
2449
2456
|
end
|
|
2450
2457
|
end
|
|
2451
2458
|
end
|
|
@@ -2481,17 +2488,16 @@ class Redis
|
|
|
2481
2488
|
# @see #watch
|
|
2482
2489
|
# @see #unwatch
|
|
2483
2490
|
def multi
|
|
2484
|
-
synchronize do |
|
|
2491
|
+
synchronize do |prior_client|
|
|
2485
2492
|
if !block_given?
|
|
2486
|
-
|
|
2493
|
+
prior_client.call([:multi])
|
|
2487
2494
|
else
|
|
2488
2495
|
begin
|
|
2489
|
-
|
|
2490
|
-
original, @client = @client, pipeline
|
|
2496
|
+
@client = Pipeline::Multi.new(prior_client)
|
|
2491
2497
|
yield(self)
|
|
2492
|
-
|
|
2498
|
+
prior_client.call_pipeline(@client)
|
|
2493
2499
|
ensure
|
|
2494
|
-
@client =
|
|
2500
|
+
@client = prior_client
|
|
2495
2501
|
end
|
|
2496
2502
|
end
|
|
2497
2503
|
end
|
|
@@ -2638,12 +2644,13 @@ class Redis
|
|
|
2638
2644
|
_eval(:evalsha, args)
|
|
2639
2645
|
end
|
|
2640
2646
|
|
|
2641
|
-
def _scan(command, cursor, args, match: nil, count: nil, &block)
|
|
2647
|
+
def _scan(command, cursor, args, match: nil, count: nil, type: nil, &block)
|
|
2642
2648
|
# SSCAN/ZSCAN/HSCAN already prepend the key to +args+.
|
|
2643
2649
|
|
|
2644
2650
|
args << cursor
|
|
2645
2651
|
args << "MATCH" << match if match
|
|
2646
2652
|
args << "COUNT" << count if count
|
|
2653
|
+
args << "TYPE" << type if type
|
|
2647
2654
|
|
|
2648
2655
|
synchronize do |client|
|
|
2649
2656
|
client.call([command] + args, &block)
|
|
@@ -2658,11 +2665,15 @@ class Redis
|
|
|
2658
2665
|
# @example Retrieve a batch of keys matching a pattern
|
|
2659
2666
|
# redis.scan(4, :match => "key:1?")
|
|
2660
2667
|
# # => ["92", ["key:13", "key:18"]]
|
|
2668
|
+
# @example Retrieve a batch of keys of a certain type
|
|
2669
|
+
# redis.scan(92, :type => "zset")
|
|
2670
|
+
# # => ["173", ["sortedset:14", "sortedset:78"]]
|
|
2661
2671
|
#
|
|
2662
2672
|
# @param [String, Integer] cursor the cursor of the iteration
|
|
2663
2673
|
# @param [Hash] options
|
|
2664
2674
|
# - `:match => String`: only return keys matching the pattern
|
|
2665
2675
|
# - `:count => Integer`: return count keys at most per iteration
|
|
2676
|
+
# - `:type => String`: return keys only of the given type
|
|
2666
2677
|
#
|
|
2667
2678
|
# @return [String, Array<String>] the next cursor and all found keys
|
|
2668
2679
|
def scan(cursor, **options)
|
|
@@ -2678,10 +2689,15 @@ class Redis
|
|
|
2678
2689
|
# redis.scan_each(:match => "key:1?") {|key| puts key}
|
|
2679
2690
|
# # => key:13
|
|
2680
2691
|
# # => key:18
|
|
2692
|
+
# @example Execute block for each key of a type
|
|
2693
|
+
# redis.scan_each(:type => "hash") {|key| puts redis.type(key)}
|
|
2694
|
+
# # => "hash"
|
|
2695
|
+
# # => "hash"
|
|
2681
2696
|
#
|
|
2682
2697
|
# @param [Hash] options
|
|
2683
2698
|
# - `:match => String`: only return keys matching the pattern
|
|
2684
2699
|
# - `:count => Integer`: return count keys at most per iteration
|
|
2700
|
+
# - `:type => String`: return keys only of the given type
|
|
2685
2701
|
#
|
|
2686
2702
|
# @return [Enumerator] an enumerator for all found keys
|
|
2687
2703
|
def scan_each(**options, &block)
|
data/lib/redis/client.rb
CHANGED
|
@@ -6,13 +6,18 @@ require "cgi"
|
|
|
6
6
|
|
|
7
7
|
class Redis
|
|
8
8
|
class Client
|
|
9
|
+
# Defaults are also used for converting string keys to symbols.
|
|
9
10
|
DEFAULTS = {
|
|
10
11
|
url: -> { ENV["REDIS_URL"] },
|
|
11
12
|
scheme: "redis",
|
|
12
13
|
host: "127.0.0.1",
|
|
13
14
|
port: 6379,
|
|
14
15
|
path: nil,
|
|
16
|
+
read_timeout: nil,
|
|
17
|
+
write_timeout: nil,
|
|
18
|
+
connect_timeout: nil,
|
|
15
19
|
timeout: 5.0,
|
|
20
|
+
username: nil,
|
|
16
21
|
password: nil,
|
|
17
22
|
db: 0,
|
|
18
23
|
driver: nil,
|
|
@@ -22,6 +27,7 @@ class Redis
|
|
|
22
27
|
reconnect_delay: 0,
|
|
23
28
|
reconnect_delay_max: 0.5,
|
|
24
29
|
inherit_socket: false,
|
|
30
|
+
logger: nil,
|
|
25
31
|
sentinels: nil,
|
|
26
32
|
role: nil
|
|
27
33
|
}.freeze
|
|
@@ -56,6 +62,10 @@ class Redis
|
|
|
56
62
|
@options[:read_timeout]
|
|
57
63
|
end
|
|
58
64
|
|
|
65
|
+
def username
|
|
66
|
+
@options[:username]
|
|
67
|
+
end
|
|
68
|
+
|
|
59
69
|
def password
|
|
60
70
|
@options[:password]
|
|
61
71
|
end
|
|
@@ -105,7 +115,17 @@ class Redis
|
|
|
105
115
|
# Don't try to reconnect when the connection is fresh
|
|
106
116
|
with_reconnect(false) do
|
|
107
117
|
establish_connection
|
|
108
|
-
|
|
118
|
+
if password
|
|
119
|
+
if username
|
|
120
|
+
begin
|
|
121
|
+
call [:auth, username, password]
|
|
122
|
+
rescue CommandError # Likely on Redis < 6
|
|
123
|
+
call [:auth, password]
|
|
124
|
+
end
|
|
125
|
+
else
|
|
126
|
+
call [:auth, password]
|
|
127
|
+
end
|
|
128
|
+
end
|
|
109
129
|
call [:select, db] if db != 0
|
|
110
130
|
call [:client, :setname, @options[:id]] if @options[:id]
|
|
111
131
|
@connector.check(self)
|
|
@@ -126,7 +146,7 @@ class Redis
|
|
|
126
146
|
reply = process([command]) { read }
|
|
127
147
|
raise reply if reply.is_a?(CommandError)
|
|
128
148
|
|
|
129
|
-
if block_given?
|
|
149
|
+
if block_given? && reply != 'QUEUED'
|
|
130
150
|
yield reply
|
|
131
151
|
else
|
|
132
152
|
reply
|
|
@@ -429,7 +449,8 @@ class Redis
|
|
|
429
449
|
defaults[:scheme] = uri.scheme
|
|
430
450
|
defaults[:host] = uri.host if uri.host
|
|
431
451
|
defaults[:port] = uri.port if uri.port
|
|
432
|
-
defaults[:
|
|
452
|
+
defaults[:username] = CGI.unescape(uri.user) if uri.user && !uri.user.empty?
|
|
453
|
+
defaults[:password] = CGI.unescape(uri.password) if uri.password && !uri.password.empty?
|
|
433
454
|
defaults[:db] = uri.path[1..-1].to_i if uri.path
|
|
434
455
|
defaults[:role] = :master
|
|
435
456
|
else
|
|
@@ -505,7 +526,7 @@ class Redis
|
|
|
505
526
|
require_relative "connection/#{driver}"
|
|
506
527
|
rescue LoadError, NameError
|
|
507
528
|
begin
|
|
508
|
-
require "connection/#{driver}"
|
|
529
|
+
require "redis/connection/#{driver}"
|
|
509
530
|
rescue LoadError, NameError => error
|
|
510
531
|
raise "Cannot load driver #{driver.inspect}: #{error.message}"
|
|
511
532
|
end
|
|
@@ -574,6 +595,7 @@ class Redis
|
|
|
574
595
|
client = Client.new(@options.merge({
|
|
575
596
|
host: sentinel[:host] || sentinel["host"],
|
|
576
597
|
port: sentinel[:port] || sentinel["port"],
|
|
598
|
+
username: sentinel[:username] || sentinel["username"],
|
|
577
599
|
password: sentinel[:password] || sentinel["password"],
|
|
578
600
|
reconnect_attempts: 0
|
|
579
601
|
}))
|
data/lib/redis/cluster.rb
CHANGED
|
@@ -128,7 +128,7 @@ class Redis
|
|
|
128
128
|
def send_command(command, &block)
|
|
129
129
|
cmd = command.first.to_s.downcase
|
|
130
130
|
case cmd
|
|
131
|
-
when 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
|
|
131
|
+
when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
|
|
132
132
|
@node.call_all(command, &block).first
|
|
133
133
|
when 'flushall', 'flushdb'
|
|
134
134
|
@node.call_master(command, &block).first
|
data/lib/redis/cluster/option.rb
CHANGED
|
@@ -18,6 +18,7 @@ class Redis
|
|
|
18
18
|
@node_opts = build_node_options(node_addrs)
|
|
19
19
|
@replica = options.delete(:replica) == true
|
|
20
20
|
add_common_node_option_if_needed(options, @node_opts, :scheme)
|
|
21
|
+
add_common_node_option_if_needed(options, @node_opts, :username)
|
|
21
22
|
add_common_node_option_if_needed(options, @node_opts, :password)
|
|
22
23
|
@options = options
|
|
23
24
|
end
|
|
@@ -63,7 +64,9 @@ class Redis
|
|
|
63
64
|
raise InvalidClientOptionError, "Invalid uri scheme #{addr}" unless VALID_SCHEMES.include?(uri.scheme)
|
|
64
65
|
|
|
65
66
|
db = uri.path.split('/')[1]&.to_i
|
|
66
|
-
|
|
67
|
+
|
|
68
|
+
{ scheme: uri.scheme, username: uri.user, password: uri.password, host: uri.host, port: uri.port, db: db }
|
|
69
|
+
.reject { |_, v| v.nil? || v == '' }
|
|
67
70
|
rescue URI::InvalidURIError => err
|
|
68
71
|
raise InvalidClientOptionError, err.message
|
|
69
72
|
end
|
|
@@ -79,7 +82,7 @@ class Redis
|
|
|
79
82
|
|
|
80
83
|
# Redis cluster node returns only host and port information.
|
|
81
84
|
# So we should complement additional information such as:
|
|
82
|
-
# scheme, password and so on.
|
|
85
|
+
# scheme, username, password and so on.
|
|
83
86
|
def add_common_node_option_if_needed(options, node_opts, key)
|
|
84
87
|
return options if options[key].nil? && node_opts.first[key].nil?
|
|
85
88
|
|
|
@@ -49,57 +49,50 @@ class Redis
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def _read_from_socket(nbytes)
|
|
52
|
-
|
|
53
|
-
read_nonblock(nbytes)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
end
|
|
67
|
-
rescue EOFError
|
|
68
|
-
raise Errno::ECONNRESET
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def _write_to_socket(data)
|
|
72
|
-
begin
|
|
73
|
-
write_nonblock(data)
|
|
74
|
-
rescue IO::WaitWritable
|
|
75
|
-
if IO.select(nil, [self], nil, @write_timeout)
|
|
76
|
-
retry
|
|
77
|
-
else
|
|
78
|
-
raise Redis::TimeoutError
|
|
79
|
-
end
|
|
80
|
-
rescue IO::WaitReadable
|
|
81
|
-
if IO.select([self], nil, nil, @write_timeout)
|
|
82
|
-
retry
|
|
83
|
-
else
|
|
84
|
-
raise Redis::TimeoutError
|
|
52
|
+
loop do
|
|
53
|
+
case chunk = read_nonblock(nbytes, exception: false)
|
|
54
|
+
when :wait_readable
|
|
55
|
+
unless wait_readable(@timeout)
|
|
56
|
+
raise Redis::TimeoutError
|
|
57
|
+
end
|
|
58
|
+
when :wait_writable
|
|
59
|
+
unless wait_writable(@timeout)
|
|
60
|
+
raise Redis::TimeoutError
|
|
61
|
+
end
|
|
62
|
+
when nil
|
|
63
|
+
raise Errno::ECONNRESET
|
|
64
|
+
when String
|
|
65
|
+
return chunk
|
|
85
66
|
end
|
|
86
67
|
end
|
|
87
|
-
rescue EOFError
|
|
88
|
-
raise Errno::ECONNRESET
|
|
89
68
|
end
|
|
90
69
|
|
|
91
|
-
def write(
|
|
92
|
-
return super(
|
|
70
|
+
def write(buffer)
|
|
71
|
+
return super(buffer) unless @write_timeout
|
|
93
72
|
|
|
94
|
-
|
|
95
|
-
|
|
73
|
+
bytes_to_write = buffer.bytesize
|
|
74
|
+
total_bytes_written = 0
|
|
96
75
|
loop do
|
|
97
|
-
|
|
76
|
+
case bytes_written = write_nonblock(buffer, exception: false)
|
|
77
|
+
when :wait_readable
|
|
78
|
+
unless wait_readable(@write_timeout)
|
|
79
|
+
raise Redis::TimeoutError
|
|
80
|
+
end
|
|
81
|
+
when :wait_writable
|
|
82
|
+
unless wait_writable(@write_timeout)
|
|
83
|
+
raise Redis::TimeoutError
|
|
84
|
+
end
|
|
85
|
+
when nil
|
|
86
|
+
raise Errno::ECONNRESET
|
|
87
|
+
when Integer
|
|
88
|
+
total_bytes_written += bytes_written
|
|
98
89
|
|
|
99
|
-
|
|
100
|
-
|
|
90
|
+
if total_bytes_written >= bytes_to_write
|
|
91
|
+
return total_bytes_written
|
|
92
|
+
end
|
|
101
93
|
|
|
102
|
-
|
|
94
|
+
buffer = buffer.byteslice(bytes_written..-1)
|
|
95
|
+
end
|
|
103
96
|
end
|
|
104
97
|
end
|
|
105
98
|
end
|
|
@@ -135,7 +128,7 @@ class Redis
|
|
|
135
128
|
raise TimeoutError
|
|
136
129
|
end
|
|
137
130
|
|
|
138
|
-
# JRuby raises Errno::EAGAIN on #read_nonblock even when
|
|
131
|
+
# JRuby raises Errno::EAGAIN on #read_nonblock even when it
|
|
139
132
|
# says it is readable (1.6.6, in both 1.8 and 1.9 mode).
|
|
140
133
|
# Use the blocking #readpartial method instead.
|
|
141
134
|
|
|
@@ -160,7 +153,7 @@ class Redis
|
|
|
160
153
|
begin
|
|
161
154
|
sock.connect_nonblock(sockaddr)
|
|
162
155
|
rescue Errno::EINPROGRESS
|
|
163
|
-
raise TimeoutError
|
|
156
|
+
raise TimeoutError unless sock.wait_writable(timeout)
|
|
164
157
|
|
|
165
158
|
begin
|
|
166
159
|
sock.connect_nonblock(sockaddr)
|
|
@@ -215,7 +208,7 @@ class Redis
|
|
|
215
208
|
begin
|
|
216
209
|
sock.connect_nonblock(sockaddr)
|
|
217
210
|
rescue Errno::EINPROGRESS
|
|
218
|
-
raise TimeoutError
|
|
211
|
+
raise TimeoutError unless sock.wait_writable(timeout)
|
|
219
212
|
|
|
220
213
|
begin
|
|
221
214
|
sock.connect_nonblock(sockaddr)
|
|
@@ -233,6 +226,18 @@ class Redis
|
|
|
233
226
|
class SSLSocket < ::OpenSSL::SSL::SSLSocket
|
|
234
227
|
include SocketMixin
|
|
235
228
|
|
|
229
|
+
unless method_defined?(:wait_readable)
|
|
230
|
+
def wait_readable(timeout = nil)
|
|
231
|
+
to_io.wait_readable(timeout)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
unless method_defined?(:wait_writable)
|
|
236
|
+
def wait_writable(timeout = nil)
|
|
237
|
+
to_io.wait_writable(timeout)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
236
241
|
def self.connect(host, port, timeout, ssl_params)
|
|
237
242
|
# Note: this is using Redis::Connection::TCPSocket
|
|
238
243
|
tcp_sock = TCPSocket.connect(host, port, timeout)
|
|
@@ -254,13 +259,13 @@ class Redis
|
|
|
254
259
|
# Instead, you have to retry.
|
|
255
260
|
ssl_sock.connect_nonblock
|
|
256
261
|
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
|
|
257
|
-
if
|
|
262
|
+
if ssl_sock.wait_readable(timeout)
|
|
258
263
|
retry
|
|
259
264
|
else
|
|
260
265
|
raise TimeoutError
|
|
261
266
|
end
|
|
262
267
|
rescue IO::WaitWritable
|
|
263
|
-
if
|
|
268
|
+
if ssl_sock.wait_writable(timeout)
|
|
264
269
|
retry
|
|
265
270
|
else
|
|
266
271
|
raise TimeoutError
|
data/lib/redis/distributed.rb
CHANGED
|
@@ -413,14 +413,14 @@ class Redis
|
|
|
413
413
|
node_for(key).rpushx(key, value)
|
|
414
414
|
end
|
|
415
415
|
|
|
416
|
-
# Remove and get the first
|
|
417
|
-
def lpop(key)
|
|
418
|
-
node_for(key).lpop(key)
|
|
416
|
+
# Remove and get the first elements in a list.
|
|
417
|
+
def lpop(key, count = nil)
|
|
418
|
+
node_for(key).lpop(key, count)
|
|
419
419
|
end
|
|
420
420
|
|
|
421
|
-
# Remove and get the last
|
|
422
|
-
def rpop(key)
|
|
423
|
-
node_for(key).rpop(key)
|
|
421
|
+
# Remove and get the last elements in a list.
|
|
422
|
+
def rpop(key, count = nil)
|
|
423
|
+
node_for(key).rpop(key, count)
|
|
424
424
|
end
|
|
425
425
|
|
|
426
426
|
# Remove the last element in a list, append it to another list and return
|
data/lib/redis/version.rb
CHANGED
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.3.1
|
|
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:
|
|
19
|
+
date: 2021-06-11 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.3.1
|
|
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.3.1
|
|
108
108
|
post_install_message:
|
|
109
109
|
rdoc_options: []
|
|
110
110
|
require_paths:
|