redis 4.2.5 → 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 +9 -0
- data/README.md +16 -11
- data/lib/redis.rb +31 -13
- data/lib/redis/client.rb +21 -4
- data/lib/redis/cluster.rb +1 -1
- data/lib/redis/cluster/option.rb +5 -2
- 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,14 @@
|
|
|
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
|
+
|
|
3
12
|
# 4.2.5
|
|
4
13
|
|
|
5
14
|
* Optimize the ruby connector write buffering. See #964.
|
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
|
|
@@ -440,7 +446,7 @@ redis = Redis.new(:driver => :synchrony)
|
|
|
440
446
|
## Testing
|
|
441
447
|
|
|
442
448
|
This library is tested against recent Ruby and Redis versions.
|
|
443
|
-
Check [
|
|
449
|
+
Check [Github Actions][gh-actions-link] for the exact versions supported.
|
|
444
450
|
|
|
445
451
|
## See Also
|
|
446
452
|
|
|
@@ -459,12 +465,11 @@ client and evangelized Redis in Rubyland. Thank you, Ezra.
|
|
|
459
465
|
requests.
|
|
460
466
|
|
|
461
467
|
|
|
462
|
-
[inchpages-image]:
|
|
463
|
-
[inchpages-link]:
|
|
464
|
-
[redis-commands]:
|
|
465
|
-
[redis-home]:
|
|
466
|
-
[redis-url]:
|
|
467
|
-
[
|
|
468
|
-
[
|
|
469
|
-
[
|
|
470
|
-
[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
|
|
|
@@ -2636,12 +2644,13 @@ class Redis
|
|
|
2636
2644
|
_eval(:evalsha, args)
|
|
2637
2645
|
end
|
|
2638
2646
|
|
|
2639
|
-
def _scan(command, cursor, args, match: nil, count: nil, &block)
|
|
2647
|
+
def _scan(command, cursor, args, match: nil, count: nil, type: nil, &block)
|
|
2640
2648
|
# SSCAN/ZSCAN/HSCAN already prepend the key to +args+.
|
|
2641
2649
|
|
|
2642
2650
|
args << cursor
|
|
2643
2651
|
args << "MATCH" << match if match
|
|
2644
2652
|
args << "COUNT" << count if count
|
|
2653
|
+
args << "TYPE" << type if type
|
|
2645
2654
|
|
|
2646
2655
|
synchronize do |client|
|
|
2647
2656
|
client.call([command] + args, &block)
|
|
@@ -2656,11 +2665,15 @@ class Redis
|
|
|
2656
2665
|
# @example Retrieve a batch of keys matching a pattern
|
|
2657
2666
|
# redis.scan(4, :match => "key:1?")
|
|
2658
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"]]
|
|
2659
2671
|
#
|
|
2660
2672
|
# @param [String, Integer] cursor the cursor of the iteration
|
|
2661
2673
|
# @param [Hash] options
|
|
2662
2674
|
# - `:match => String`: only return keys matching the pattern
|
|
2663
2675
|
# - `:count => Integer`: return count keys at most per iteration
|
|
2676
|
+
# - `:type => String`: return keys only of the given type
|
|
2664
2677
|
#
|
|
2665
2678
|
# @return [String, Array<String>] the next cursor and all found keys
|
|
2666
2679
|
def scan(cursor, **options)
|
|
@@ -2676,10 +2689,15 @@ class Redis
|
|
|
2676
2689
|
# redis.scan_each(:match => "key:1?") {|key| puts key}
|
|
2677
2690
|
# # => key:13
|
|
2678
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"
|
|
2679
2696
|
#
|
|
2680
2697
|
# @param [Hash] options
|
|
2681
2698
|
# - `:match => String`: only return keys matching the pattern
|
|
2682
2699
|
# - `:count => Integer`: return count keys at most per iteration
|
|
2700
|
+
# - `:type => String`: return keys only of the given type
|
|
2683
2701
|
#
|
|
2684
2702
|
# @return [Enumerator] an enumerator for all found keys
|
|
2685
2703
|
def scan_each(**options, &block)
|
data/lib/redis/client.rb
CHANGED
|
@@ -17,6 +17,7 @@ class Redis
|
|
|
17
17
|
write_timeout: nil,
|
|
18
18
|
connect_timeout: nil,
|
|
19
19
|
timeout: 5.0,
|
|
20
|
+
username: nil,
|
|
20
21
|
password: nil,
|
|
21
22
|
db: 0,
|
|
22
23
|
driver: nil,
|
|
@@ -61,6 +62,10 @@ class Redis
|
|
|
61
62
|
@options[:read_timeout]
|
|
62
63
|
end
|
|
63
64
|
|
|
65
|
+
def username
|
|
66
|
+
@options[:username]
|
|
67
|
+
end
|
|
68
|
+
|
|
64
69
|
def password
|
|
65
70
|
@options[:password]
|
|
66
71
|
end
|
|
@@ -110,7 +115,17 @@ class Redis
|
|
|
110
115
|
# Don't try to reconnect when the connection is fresh
|
|
111
116
|
with_reconnect(false) do
|
|
112
117
|
establish_connection
|
|
113
|
-
|
|
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
|
|
114
129
|
call [:select, db] if db != 0
|
|
115
130
|
call [:client, :setname, @options[:id]] if @options[:id]
|
|
116
131
|
@connector.check(self)
|
|
@@ -131,7 +146,7 @@ class Redis
|
|
|
131
146
|
reply = process([command]) { read }
|
|
132
147
|
raise reply if reply.is_a?(CommandError)
|
|
133
148
|
|
|
134
|
-
if block_given?
|
|
149
|
+
if block_given? && reply != 'QUEUED'
|
|
135
150
|
yield reply
|
|
136
151
|
else
|
|
137
152
|
reply
|
|
@@ -434,7 +449,8 @@ class Redis
|
|
|
434
449
|
defaults[:scheme] = uri.scheme
|
|
435
450
|
defaults[:host] = uri.host if uri.host
|
|
436
451
|
defaults[:port] = uri.port if uri.port
|
|
437
|
-
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?
|
|
438
454
|
defaults[:db] = uri.path[1..-1].to_i if uri.path
|
|
439
455
|
defaults[:role] = :master
|
|
440
456
|
else
|
|
@@ -510,7 +526,7 @@ class Redis
|
|
|
510
526
|
require_relative "connection/#{driver}"
|
|
511
527
|
rescue LoadError, NameError
|
|
512
528
|
begin
|
|
513
|
-
require "connection/#{driver}"
|
|
529
|
+
require "redis/connection/#{driver}"
|
|
514
530
|
rescue LoadError, NameError => error
|
|
515
531
|
raise "Cannot load driver #{driver.inspect}: #{error.message}"
|
|
516
532
|
end
|
|
@@ -579,6 +595,7 @@ class Redis
|
|
|
579
595
|
client = Client.new(@options.merge({
|
|
580
596
|
host: sentinel[:host] || sentinel["host"],
|
|
581
597
|
port: sentinel[:port] || sentinel["port"],
|
|
598
|
+
username: sentinel[:username] || sentinel["username"],
|
|
582
599
|
password: sentinel[:password] || sentinel["password"],
|
|
583
600
|
reconnect_attempts: 0
|
|
584
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
|
|
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:
|