redis-client 0.15.0 → 0.17.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -2
- data/Gemfile.lock +2 -2
- data/README.md +43 -8
- data/lib/redis_client/config.rb +5 -3
- data/lib/redis_client/ruby_connection/buffered_io.rb +0 -4
- data/lib/redis_client/ruby_connection/resp3.rb +2 -0
- data/lib/redis_client/ruby_connection.rb +0 -7
- data/lib/redis_client/sentinel_config.rb +18 -6
- data/lib/redis_client/version.rb +1 -1
- data/lib/redis_client.rb +7 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e73c2e13870d3adcb345e544fe99bbffa6ad1bf5f7267203e49f838c56a7492
|
4
|
+
data.tar.gz: d090544eb97a93ad0d21d5a6c14c40ffb3ca384425ccf27d82c797f0f7e2d35a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60e0fbf2c30888ac05855af2ba6b145ac96e0e011cc58d989f66e9379baa549c9af1ad2f7077ce431b334d6b1318b83463eac7bcb7a323752c79644e0dbce495
|
7
|
+
data.tar.gz: 1e3e10ef87472a412239261c0642e134f9521e83e49def834bb76b1aa6481c8e8fc9b13cfe1916c0f0ed43af8799a331e9649caa61155ce9eeb8391b0c15c98a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 0.17.1
|
4
|
+
|
5
|
+
- Add support for `NaN` in RESP3 protocol doubles.
|
6
|
+
This was initially missing from the spec and added about a year ago.
|
7
|
+
|
8
|
+
# 0.17.0
|
9
|
+
|
10
|
+
- Adds `sentinel_username` and `sentinel_password` options for `RedisClient#sentinel`
|
11
|
+
|
12
|
+
# 0.16.0
|
13
|
+
|
14
|
+
- Add `RedisClient#disable_reconnection`.
|
15
|
+
- Reverted the special discard of connection. A regular `close(2)` should be enough.
|
16
|
+
|
3
17
|
# 0.15.0
|
4
18
|
|
5
19
|
- Discard sockets rather than explictly close them when a fork is detected. #126.
|
@@ -66,7 +80,7 @@
|
|
66
80
|
|
67
81
|
- Make the client resilient to `Timeout.timeout` or `Thread#kill` use (it still is very much discouraged to use either).
|
68
82
|
Use of async interrupts could cause responses to be interleaved.
|
69
|
-
- hiredis: handle commands returning a top-level `false` (no command does this today, but some extensions might).
|
83
|
+
- hiredis: handle commands returning a top-level `false` (no command does this today, but some extensions might).
|
70
84
|
- Workaround a bug in Ruby 2.6 causing a crash if the `debug` gem is enabled when `redis-client` is being required. Fix: #48
|
71
85
|
|
72
86
|
# 0.8.0
|
@@ -85,7 +99,7 @@
|
|
85
99
|
|
86
100
|
- Raise a distinct `RedisClient::OutOfMemoryError`, for Redis `OOM` errors.
|
87
101
|
- Fix the instrumentation API to be called even for authentication commands.
|
88
|
-
- Fix `url:` configuration to accept a trailing slash.
|
102
|
+
- Fix `url:` configuration to accept a trailing slash.
|
89
103
|
|
90
104
|
# 0.7.1
|
91
105
|
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
redis-client (0.
|
4
|
+
redis-client (0.17.1)
|
5
5
|
connection_pool
|
6
6
|
|
7
7
|
GEM
|
@@ -19,7 +19,7 @@ GEM
|
|
19
19
|
ast (~> 2.4.1)
|
20
20
|
rainbow (3.1.1)
|
21
21
|
rake (13.0.6)
|
22
|
-
rake-compiler (1.2.
|
22
|
+
rake-compiler (1.2.5)
|
23
23
|
rake
|
24
24
|
redis (4.6.0)
|
25
25
|
regexp_parser (2.5.0)
|
data/README.md
CHANGED
@@ -42,7 +42,7 @@ redis.with do |r|
|
|
42
42
|
end
|
43
43
|
```
|
44
44
|
|
45
|
-
If you are working in a single
|
45
|
+
If you are working in a single-threaded environment, or wish to use your own connection pooling mechanism,
|
46
46
|
you can obtain a raw client with `#new_client`
|
47
47
|
|
48
48
|
```ruby
|
@@ -67,11 +67,11 @@ redis.call("GET", "mykey")
|
|
67
67
|
- `host`: The server hostname or IP address. Defaults to `"localhost"`.
|
68
68
|
- `port`: The server port. Defaults to `6379`.
|
69
69
|
- `path`: The path to a UNIX socket, if set `url`, `host` and `port` are ignored.
|
70
|
-
- `ssl`:
|
70
|
+
- `ssl`: Whether to connect using SSL or not.
|
71
71
|
- `ssl_params`: A configuration Hash passed to [`OpenSSL::SSL::SSLContext#set_params`](https://www.rubydoc.info/stdlib/openssl/OpenSSL%2FSSL%2FSSLContext:set_params), notable options include:
|
72
72
|
- `cert`: The path to the client certificate (e.g. `client.crt`).
|
73
73
|
- `key`: The path to the client key (e.g. `client.key`).
|
74
|
-
- `ca_file`: The certificate authority to use, useful for self
|
74
|
+
- `ca_file`: The certificate authority to use, useful for self-signed certificates (e.g. `ca.crt`),
|
75
75
|
- `db`: The database to select after connecting, defaults to `0`.
|
76
76
|
- `id` ID for the client connection, assigns name to current connection by sending `CLIENT SETNAME`.
|
77
77
|
- `username` Username to authenticate against server, defaults to `"default"`.
|
@@ -83,7 +83,7 @@ redis.call("GET", "mykey")
|
|
83
83
|
- `reconnect_attempts`: Specify how many times the client should retry to send queries. Defaults to `0`. Makes sure to read the [reconnection section](#reconnection) before enabling it.
|
84
84
|
- `circuit_breaker`: A Hash with circuit breaker configuration. Defaults to `nil`. See the [circuit breaker section](#circuit-breaker) for details.
|
85
85
|
- `protocol:` The version of the RESP protocol to use. Default to `3`.
|
86
|
-
- `custom`: A user
|
86
|
+
- `custom`: A user-owned value ignored by `redis-client` but available as `Config#custom`. This can be used to hold middleware configurations and other user-specific metadata.
|
87
87
|
|
88
88
|
### Sentinel support
|
89
89
|
|
@@ -128,6 +128,41 @@ but a few so that if one is down the client will try the next one. The client
|
|
128
128
|
is able to remember the last Sentinel that was able to reply correctly and will
|
129
129
|
use it for the next requests.
|
130
130
|
|
131
|
+
To [authenticate](https://redis.io/docs/management/sentinel/#configuring-sentinel-instances-with-authentication) Sentinel itself, you can specify the `sentinel_username` and `sentinel_password` options per instance. Exclude the `sentinel_username` option if you're using password-only authentication.
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
SENTINELS = [{ host: '127.0.0.1', port: 26380},
|
135
|
+
{ host: '127.0.0.1', port: 26381}]
|
136
|
+
|
137
|
+
redis_config = RedisClient.sentinel(name: 'mymaster', sentinel_username: 'appuser', sentinel_password: 'mysecret', sentinels: SENTINELS, role: :master)
|
138
|
+
```
|
139
|
+
|
140
|
+
If you specify a username and/or password at the top level for your main Redis instance, Sentinel *will not* using thouse credentials
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
# Use 'mysecret' to authenticate against the mymaster instance, but skip authentication for the sentinels:
|
144
|
+
SENTINELS = [{ host: '127.0.0.1', port: 26380 },
|
145
|
+
{ host: '127.0.0.1', port: 26381 }]
|
146
|
+
|
147
|
+
redis_config = RedisClient.sentinel(name: 'mymaster', sentinels: SENTINELS, role: :master, password: 'mysecret')
|
148
|
+
```
|
149
|
+
|
150
|
+
So you have to provide Sentinel credential and Redis explictly even they are the same
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
# Use 'mysecret' to authenticate against the mymaster instance and sentinel
|
154
|
+
SENTINELS = [{ host: '127.0.0.1', port: 26380 },
|
155
|
+
{ host: '127.0.0.1', port: 26381 }]
|
156
|
+
|
157
|
+
redis_config = RedisClient.sentinel(name: 'mymaster', sentinels: SENTINELS, role: :master, password: 'mysecret', sentinel_password: 'mysecret')
|
158
|
+
```
|
159
|
+
|
160
|
+
Also the `name`, `password`, `username` and `db` for Redis instance can be passed as an url:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
redis_config = RedisClient.sentinel(url: "redis://appuser:mysecret@mymaster/10", sentinels: SENTINELS, role: :master)
|
164
|
+
```
|
165
|
+
|
131
166
|
### Type support
|
132
167
|
|
133
168
|
Only a select few Ruby types are supported as arguments beside strings.
|
@@ -344,7 +379,7 @@ end
|
|
344
379
|
```
|
345
380
|
|
346
381
|
*Note*: pubsub connections are stateful, as such they won't ever reconnect automatically.
|
347
|
-
The caller is
|
382
|
+
The caller is responsible for reconnecting if the connection is lost and to resubscribe to
|
348
383
|
all channels.
|
349
384
|
|
350
385
|
## Production
|
@@ -380,7 +415,7 @@ redis_config = RedisClient.config(middlewares: [AnotherRedisInstrumentation])
|
|
380
415
|
redis_config.new_client
|
381
416
|
```
|
382
417
|
|
383
|
-
If middlewares need a client
|
418
|
+
If middlewares need a client-specific configuration, `Config#custom` can be used
|
384
419
|
|
385
420
|
```ruby
|
386
421
|
module MyGlobalRedisInstrumentation
|
@@ -454,9 +489,9 @@ redis_config = RedisClient.config(reconnect_attempts: [0, 0.05, 0.1])
|
|
454
489
|
```
|
455
490
|
|
456
491
|
This configuration is generally used when the Redis server is expected to failover or recover relatively quickly and
|
457
|
-
that it's not really
|
492
|
+
that it's not really possible to continue without issuing the command.
|
458
493
|
|
459
|
-
When the Redis server is used as an ephemeral cache, circuit breakers are generally
|
494
|
+
When the Redis server is used as an ephemeral cache, circuit breakers are generally preferred.
|
460
495
|
|
461
496
|
### Circuit Breaker
|
462
497
|
|
data/lib/redis_client/config.rb
CHANGED
@@ -159,21 +159,23 @@ class RedisClient
|
|
159
159
|
host: nil,
|
160
160
|
port: nil,
|
161
161
|
path: nil,
|
162
|
+
username: nil,
|
163
|
+
password: nil,
|
162
164
|
**kwargs
|
163
165
|
)
|
164
166
|
if url
|
165
167
|
url_config = URLConfig.new(url)
|
166
168
|
kwargs = {
|
167
169
|
ssl: url_config.ssl?,
|
168
|
-
username: url_config.username,
|
169
|
-
password: url_config.password,
|
170
170
|
db: url_config.db,
|
171
171
|
}.compact.merge(kwargs)
|
172
172
|
host ||= url_config.host
|
173
173
|
port ||= url_config.port
|
174
|
+
username ||= url_config.username
|
175
|
+
password ||= url_config.password
|
174
176
|
end
|
175
177
|
|
176
|
-
super(**kwargs)
|
178
|
+
super(username: username, password: password, **kwargs)
|
177
179
|
|
178
180
|
@host = host || DEFAULT_HOST
|
179
181
|
@port = Integer(port || DEFAULT_PORT)
|
@@ -9,8 +9,16 @@ class RedisClient
|
|
9
9
|
|
10
10
|
attr_reader :name
|
11
11
|
|
12
|
-
def initialize(
|
13
|
-
|
12
|
+
def initialize(
|
13
|
+
sentinels:,
|
14
|
+
sentinel_password: nil,
|
15
|
+
sentinel_username: nil,
|
16
|
+
role: :master,
|
17
|
+
name: nil,
|
18
|
+
url: nil,
|
19
|
+
**client_config
|
20
|
+
)
|
21
|
+
unless %i(master replica slave).include?(role.to_sym)
|
14
22
|
raise ArgumentError, "Expected role to be either :master or :replica, got: #{role.inspect}"
|
15
23
|
end
|
16
24
|
|
@@ -30,7 +38,11 @@ class RedisClient
|
|
30
38
|
end
|
31
39
|
|
32
40
|
@to_list_of_hash = @to_hash = nil
|
33
|
-
@extra_config = {
|
41
|
+
@extra_config = {
|
42
|
+
username: sentinel_username,
|
43
|
+
password: sentinel_password,
|
44
|
+
db: nil,
|
45
|
+
}
|
34
46
|
if client_config[:protocol] == 2
|
35
47
|
@extra_config[:protocol] = client_config[:protocol]
|
36
48
|
@to_list_of_hash = lambda do |may_be_a_list|
|
@@ -43,7 +55,7 @@ class RedisClient
|
|
43
55
|
end
|
44
56
|
|
45
57
|
@sentinels = {}.compare_by_identity
|
46
|
-
@role = role
|
58
|
+
@role = role.to_sym
|
47
59
|
@mutex = Mutex.new
|
48
60
|
@config = nil
|
49
61
|
|
@@ -106,9 +118,9 @@ class RedisClient
|
|
106
118
|
sentinels.map do |sentinel|
|
107
119
|
case sentinel
|
108
120
|
when String
|
109
|
-
Config.new(**@client_config, **@extra_config, url: sentinel
|
121
|
+
Config.new(**@client_config, **@extra_config, url: sentinel)
|
110
122
|
else
|
111
|
-
Config.new(**@client_config, **@extra_config, **sentinel
|
123
|
+
Config.new(**@client_config, **@extra_config, **sentinel)
|
112
124
|
end
|
113
125
|
end
|
114
126
|
end
|
data/lib/redis_client/version.rb
CHANGED
data/lib/redis_client.rb
CHANGED
@@ -175,6 +175,10 @@ class RedisClient
|
|
175
175
|
"#<#{self.class.name} #{config.server_url}#{id_string}>"
|
176
176
|
end
|
177
177
|
|
178
|
+
def server_url
|
179
|
+
config.server_url
|
180
|
+
end
|
181
|
+
|
178
182
|
def size
|
179
183
|
1
|
180
184
|
end
|
@@ -358,9 +362,8 @@ class RedisClient
|
|
358
362
|
self
|
359
363
|
end
|
360
364
|
|
361
|
-
def
|
362
|
-
|
363
|
-
self
|
365
|
+
def disable_reconnection(&block)
|
366
|
+
ensure_connected(retryable: false, &block)
|
364
367
|
end
|
365
368
|
|
366
369
|
def pipelined
|
@@ -623,7 +626,7 @@ class RedisClient
|
|
623
626
|
end
|
624
627
|
|
625
628
|
def ensure_connected(retryable: true)
|
626
|
-
|
629
|
+
close if !config.inherit_socket && @pid != PIDCache.pid
|
627
630
|
|
628
631
|
if @disable_reconnection
|
629
632
|
if block_given?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: connection_pool
|