solid-redis 1.0.1 → 1.0.3
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 +101 -0
- data/README.md +23 -3
- data/lib/solid_redis/client.rb +12 -7
- data/lib/solid_redis/cluster/command_key.rb +2 -1
- data/lib/solid_redis/cluster_client.rb +8 -1
- data/lib/solid_redis/config.rb +6 -4
- data/lib/solid_redis/resp.rb +41 -7
- data/lib/solid_redis/subscription.rb +6 -0
- data/lib/solid_redis/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1a92b96853d5d381ae812b7440c9b50a718f9b67fc678e0cbee1d0c8014fc16
|
|
4
|
+
data.tar.gz: 679a2723c695c95b68f95432006fe93e111c2318106b0384e7a409eca475b480
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2ea6594459de7d81b8e8fbe1f0f323a397a6c99ff145489ecba44e0ff6ecb8c2409236283a0d21add112033377ceaab4ce787e7021afbfd6c79d18ffc1991f92
|
|
7
|
+
data.tar.gz: 4ddc0772aeb012163fced9a0bdca65c8da9d21019e82f25b36254fe2c0c3b32312052de47e707b1bcdf64fc35663363db4775155dcc4143ba9c44db93cdc6d48
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file. The format
|
|
4
|
+
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
|
|
5
|
+
project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [1.0.3] - 2026-09-27
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Consume complete RESP arrays, maps, sets, pushes, and attributes before
|
|
12
|
+
raising nested Redis errors, preventing connection desynchronization.
|
|
13
|
+
- Handle `:wait_writable` during non-blocking reads and discard connections
|
|
14
|
+
after protocol errors without replaying commands.
|
|
15
|
+
- Retry `TRYAGAIN` and `CLUSTERDOWN` pipeline replies consistently with direct
|
|
16
|
+
Cluster calls, and clear `ASKING` state before refreshing the topology.
|
|
17
|
+
- Route `MEMORY USAGE` to the node owning its key.
|
|
18
|
+
- Preserve an explicitly configured `db` when a Redis URL is also provided.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Clarify that Cluster commands are grouped into per-node pipelines rather
|
|
23
|
+
than sent concurrently.
|
|
24
|
+
|
|
25
|
+
## [1.0.2] - 2026-09-27
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- `CHANGELOG.md` and `changelog_uri` gem metadata.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- README: describe the test suite's fake server and how to check against a
|
|
34
|
+
real Redis or local cluster.
|
|
35
|
+
|
|
36
|
+
## [1.0.1] - 2026-09-27
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- README: document the Cluster architecture (`ClusterConfig`/`ClusterState`).
|
|
41
|
+
|
|
42
|
+
## [1.0.0] - 2026-09-27
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- `Client#blocking_call(timeout, *command)` and `#blocking_call_v` for BLPOP,
|
|
47
|
+
BRPOP, BZPOPMIN, XREAD BLOCK and similar commands. The read timeout is
|
|
48
|
+
extended by `timeout`; `nil`/`0` waits forever. Blocking commands are never
|
|
49
|
+
retried. Also available on `Pool`.
|
|
50
|
+
- Pub/Sub: `Config#new_subscription` and `SentinelConfig#new_subscription`
|
|
51
|
+
return a `SolidRedis::Subscription` bound to a dedicated connection, with
|
|
52
|
+
`subscribe`/`psubscribe`/`ssubscribe`, `next_message(timeout:)`,
|
|
53
|
+
`each_message`, `ping`, and automatic resubscription after reconnect.
|
|
54
|
+
- Redis Cluster: `SolidRedis.cluster(nodes:, max_redirections:, **options)`
|
|
55
|
+
builds a shareable `ClusterConfig`. Each Ractor keeps its own `ClusterState`
|
|
56
|
+
(slot table and per-node clients). `ClusterClient` handles `MOVED`, `ASK`,
|
|
57
|
+
`TRYAGAIN` and `CLUSTERDOWN`, extracts routing keys (hash tags, EVAL/FCALL,
|
|
58
|
+
XREAD STREAMS, ZUNION-style commands) and runs pipelines grouped per node
|
|
59
|
+
while preserving reply order.
|
|
60
|
+
- `RESP::Reader#with_timeout` and `#wait_readable`.
|
|
61
|
+
|
|
62
|
+
## [0.2.1] - 2026-09-27
|
|
63
|
+
|
|
64
|
+
### Changed
|
|
65
|
+
|
|
66
|
+
- README: refresh the downloads badge.
|
|
67
|
+
|
|
68
|
+
## [0.2.0] - 2026-09-27
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- `Client#pipelined(exception: false)` returns `CommandError` instances in
|
|
73
|
+
place instead of raising the first one.
|
|
74
|
+
|
|
75
|
+
## [0.1.1] - 2026-09-27
|
|
76
|
+
|
|
77
|
+
### Added
|
|
78
|
+
|
|
79
|
+
- README usage examples.
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
|
|
83
|
+
- Require Ruby >= 3.1; CI runs Ruby 3.1 through 4.0.
|
|
84
|
+
|
|
85
|
+
## [0.1.0] - 2026-09-27
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- Initial release: immutable, Ractor-shareable `Config` and `SentinelConfig`
|
|
90
|
+
with per-Ractor `SentinelState`, `Client` (RESP2/RESP3, TCP, Unix socket,
|
|
91
|
+
TLS, reconnection), `Pool` owned by a single Ractor, pipelines, and
|
|
92
|
+
lifecycle callbacks via `callback-collection`.
|
|
93
|
+
|
|
94
|
+
[1.0.3]: https://github.com/nicolasva/solid-redis/compare/v1.0.2...v1.0.3
|
|
95
|
+
[1.0.2]: https://github.com/nicolasva/solid-redis/compare/v1.0.1...v1.0.2
|
|
96
|
+
[1.0.1]: https://github.com/nicolasva/solid-redis/compare/v1.0.0...v1.0.1
|
|
97
|
+
[1.0.0]: https://github.com/nicolasva/solid-redis/compare/v0.2.1...v1.0.0
|
|
98
|
+
[0.2.1]: https://github.com/nicolasva/solid-redis/compare/v0.2.0...v0.2.1
|
|
99
|
+
[0.2.0]: https://github.com/nicolasva/solid-redis/compare/v0.1.1...v0.2.0
|
|
100
|
+
[0.1.1]: https://github.com/nicolasva/solid-redis/compare/v0.1.0...v0.1.1
|
|
101
|
+
[0.1.0]: https://github.com/nicolasva/solid-redis/releases/tag/v0.1.0
|
data/README.md
CHANGED
|
@@ -272,9 +272,9 @@ client.call("GET", "user:1")
|
|
|
272
272
|
client.call("MGET", "{user:1}.name", "{user:1}.email") # same slot via hash tag
|
|
273
273
|
|
|
274
274
|
client.pipelined do |pipeline|
|
|
275
|
-
pipeline.call("GET", "a") # commands are grouped
|
|
276
|
-
pipeline.call("GET", "b") #
|
|
277
|
-
pipeline.call("PING") #
|
|
275
|
+
pipeline.call("GET", "a") # commands are grouped into one pipeline
|
|
276
|
+
pipeline.call("GET", "b") # per node, and results come back
|
|
277
|
+
pipeline.call("PING") # in their original order
|
|
278
278
|
end
|
|
279
279
|
|
|
280
280
|
pool = CLUSTER.new_pool(size: 5) # a pool of cluster clients
|
|
@@ -308,6 +308,10 @@ Direct Redis options:
|
|
|
308
308
|
| `ssl` | `false` | Enable TLS |
|
|
309
309
|
| `ssl_params` | | Immutable `OpenSSL::SSL::SSLContext` attributes |
|
|
310
310
|
|
|
311
|
+
An explicit `db:` option takes precedence over a database selected by the URL
|
|
312
|
+
path or `?db=` query parameter. When neither specifies a database, it defaults
|
|
313
|
+
to `0`.
|
|
314
|
+
|
|
311
315
|
Sentinel additionally requires `name` and `sentinels`, and accepts `role`,
|
|
312
316
|
`sentinel_username`, `sentinel_password`, `sentinel_ssl`, and
|
|
313
317
|
`sentinel_ssl_params`. Sentinel defaults to two reconnect attempts.
|
|
@@ -589,6 +593,22 @@ bundle exec rake
|
|
|
589
593
|
The default task runs the Minitest suite and builds the gem in `pkg/`.
|
|
590
594
|
CI runs the suite on Ruby 3.1 through 4.0.
|
|
591
595
|
|
|
596
|
+
The suite needs no running Redis: it uses an in-process fake server
|
|
597
|
+
(`test/support/fake_redis_server.rb`) that speaks RESP2/RESP3, Sentinel,
|
|
598
|
+
Pub/Sub and a three-node Cluster topology. To try a specific Ruby version:
|
|
599
|
+
|
|
600
|
+
```sh
|
|
601
|
+
RBENV_VERSION=4.0.1 rbenv exec bundle exec rake test
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
To exercise the client against a real server, start `redis-server` and run
|
|
605
|
+
snippets from the examples above with `bundle exec ruby -Ilib`. A local
|
|
606
|
+
cluster for manual checks can be created with three
|
|
607
|
+
`redis-server --port 700X --cluster-enabled yes` processes followed by
|
|
608
|
+
`redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 --cluster-yes`.
|
|
609
|
+
|
|
610
|
+
The changelog lives in `CHANGELOG.md`; add an entry for every release.
|
|
611
|
+
|
|
592
612
|
## Publishing
|
|
593
613
|
|
|
594
614
|
Releases use RubyGems Trusted Publishing. Configure a pending trusted
|
data/lib/solid_redis/client.rb
CHANGED
|
@@ -44,10 +44,8 @@ module SolidRedis
|
|
|
44
44
|
begin
|
|
45
45
|
write(RESP.encode(command))
|
|
46
46
|
@reader.with_timeout(read_timeout) { @reader.read }
|
|
47
|
-
rescue ConnectionError, IO::WaitReadable, IO::WaitWritable, SystemCallError => error
|
|
48
|
-
|
|
49
|
-
config.reset if config.sentinel?
|
|
50
|
-
config.notify(:connection_error, error.class.name, error.message)
|
|
47
|
+
rescue ProtocolError, ConnectionError, IO::WaitReadable, IO::WaitWritable, SystemCallError => error
|
|
48
|
+
handle_connection_failure(error)
|
|
51
49
|
raise error if error.is_a?(Error)
|
|
52
50
|
|
|
53
51
|
raise ConnectionError, error.message, cause: error
|
|
@@ -96,10 +94,11 @@ module SolidRedis
|
|
|
96
94
|
begin
|
|
97
95
|
connect unless connected?
|
|
98
96
|
yield
|
|
97
|
+
rescue ProtocolError => error
|
|
98
|
+
handle_connection_failure(error)
|
|
99
|
+
raise
|
|
99
100
|
rescue ConnectionError, IO::WaitReadable, IO::WaitWritable, SystemCallError => error
|
|
100
|
-
|
|
101
|
-
config.reset if config.sentinel?
|
|
102
|
-
config.notify(:connection_error, error.class.name, error.message)
|
|
101
|
+
handle_connection_failure(error)
|
|
103
102
|
if attempts < config.reconnect_attempts
|
|
104
103
|
attempts += 1
|
|
105
104
|
retry
|
|
@@ -110,6 +109,12 @@ module SolidRedis
|
|
|
110
109
|
end
|
|
111
110
|
end
|
|
112
111
|
|
|
112
|
+
def handle_connection_failure(error)
|
|
113
|
+
close
|
|
114
|
+
config.reset if config.sentinel?
|
|
115
|
+
config.notify(:connection_error, error.class.name, error.message)
|
|
116
|
+
end
|
|
117
|
+
|
|
113
118
|
def connect
|
|
114
119
|
@target = config.sentinel? ? config.resolve : config
|
|
115
120
|
@socket = open_socket(@target)
|
|
@@ -8,7 +8,7 @@ module SolidRedis
|
|
|
8
8
|
KEYLESS = Ractor.make_shareable(
|
|
9
9
|
%w[
|
|
10
10
|
ACL ASKING AUTH BGREWRITEAOF BGSAVE CLIENT CLUSTER COMMAND CONFIG DBSIZE DEBUG DISCARD ECHO EXEC
|
|
11
|
-
FAILOVER FLUSHALL FLUSHDB FUNCTION HELLO INFO LASTSAVE LATENCY LOLWUT
|
|
11
|
+
FAILOVER FLUSHALL FLUSHDB FUNCTION HELLO INFO LASTSAVE LATENCY LOLWUT MODULE MONITOR MULTI PING
|
|
12
12
|
PSUBSCRIBE PUBLISH PUBSUB PUNSUBSCRIBE QUIT RANDOMKEY READONLY READWRITE REPLICAOF RESET ROLE SAVE
|
|
13
13
|
SCAN SCRIPT SELECT SHUTDOWN SLAVEOF SLOWLOG SUBSCRIBE SWAPDB SYNC TIME UNSUBSCRIBE UNWATCH WAIT
|
|
14
14
|
].to_h { |name| [name, true] },
|
|
@@ -42,6 +42,7 @@ module SolidRedis
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
case name
|
|
45
|
+
when "MEMORY" then command[1].to_s.casecmp?("USAGE") ? command[2] : nil
|
|
45
46
|
when "XGROUP", "XINFO", "OBJECT" then command[2]
|
|
46
47
|
when "MIGRATE" then command[3].to_s.empty? ? nil : command[3]
|
|
47
48
|
else command[1]
|
|
@@ -7,6 +7,7 @@ module SolidRedis
|
|
|
7
7
|
class ClusterClient
|
|
8
8
|
REDIRECTION = /\A(MOVED|ASK) (\d+) (\S+):(\d+)\z/
|
|
9
9
|
RETRY_DELAY = 0.05
|
|
10
|
+
TRANSIENT_ERRORS = %w[TRYAGAIN CLUSTERDOWN].freeze
|
|
10
11
|
|
|
11
12
|
attr_reader :config
|
|
12
13
|
|
|
@@ -49,7 +50,8 @@ module SolidRedis
|
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
results.each_with_index do |result, index|
|
|
52
|
-
next unless result.is_a?(CommandError)
|
|
53
|
+
next unless result.is_a?(CommandError)
|
|
54
|
+
next unless result.message.match?(REDIRECTION) || transient_error?(result)
|
|
53
55
|
|
|
54
56
|
results[index] = begin
|
|
55
57
|
call_v(commands[index])
|
|
@@ -107,6 +109,7 @@ module SolidRedis
|
|
|
107
109
|
redirections += 1
|
|
108
110
|
raise FailoverError, "Cluster unavailable: #{error.message}" if redirections > config.max_redirections
|
|
109
111
|
|
|
112
|
+
asking = false
|
|
110
113
|
sleep RETRY_DELAY
|
|
111
114
|
config.state.refresh
|
|
112
115
|
node = node_for(command)
|
|
@@ -129,6 +132,10 @@ module SolidRedis
|
|
|
129
132
|
key ? config.state.node_for_slot(Cluster::KeySlot.for(key)) : config.state.any_node
|
|
130
133
|
end
|
|
131
134
|
|
|
135
|
+
def transient_error?(error)
|
|
136
|
+
error.message.start_with?(*TRANSIENT_ERRORS)
|
|
137
|
+
end
|
|
138
|
+
|
|
132
139
|
def client_for(node)
|
|
133
140
|
@clients[node.server_key] ||= node.new_client(name: @name)
|
|
134
141
|
end
|
data/lib/solid_redis/config.rb
CHANGED
|
@@ -6,6 +6,7 @@ module SolidRedis
|
|
|
6
6
|
class Config
|
|
7
7
|
DEFAULT_TIMEOUT = 1.0
|
|
8
8
|
DEFAULT_PORT = 6379
|
|
9
|
+
UNSPECIFIED = Object.new.freeze
|
|
9
10
|
|
|
10
11
|
attr_reader :host, :port, :path, :username, :password, :db,
|
|
11
12
|
:connect_timeout, :read_timeout, :write_timeout, :reconnect_attempts,
|
|
@@ -18,7 +19,7 @@ module SolidRedis
|
|
|
18
19
|
path: nil,
|
|
19
20
|
username: nil,
|
|
20
21
|
password: nil,
|
|
21
|
-
db:
|
|
22
|
+
db: UNSPECIFIED,
|
|
22
23
|
timeout: DEFAULT_TIMEOUT,
|
|
23
24
|
connect_timeout: timeout,
|
|
24
25
|
read_timeout: timeout,
|
|
@@ -35,9 +36,10 @@ module SolidRedis
|
|
|
35
36
|
path = values[:path]
|
|
36
37
|
username ||= values[:username]
|
|
37
38
|
password ||= values[:password]
|
|
38
|
-
db = values[:db]
|
|
39
|
+
db = values[:db] if db.equal?(UNSPECIFIED) && !values[:db].nil?
|
|
39
40
|
ssl ||= values[:ssl]
|
|
40
41
|
end
|
|
42
|
+
db = 0 if db.equal?(UNSPECIFIED)
|
|
41
43
|
|
|
42
44
|
@host = String(host).dup.freeze unless path
|
|
43
45
|
@port = Integer(port) unless path
|
|
@@ -140,10 +142,10 @@ module SolidRedis
|
|
|
140
142
|
end
|
|
141
143
|
|
|
142
144
|
def query_db(uri)
|
|
143
|
-
return
|
|
145
|
+
return unless uri.query
|
|
144
146
|
|
|
145
147
|
value = URI.decode_www_form(uri.query).to_h["db"]
|
|
146
|
-
|
|
148
|
+
Integer(value) if value
|
|
147
149
|
end
|
|
148
150
|
|
|
149
151
|
def decoded(value)
|
data/lib/solid_redis/resp.rb
CHANGED
|
@@ -72,7 +72,7 @@ module SolidRedis
|
|
|
72
72
|
when "~", ">" then read_collection(exception)
|
|
73
73
|
when "=" then read_verbatim
|
|
74
74
|
when "!" then error_response(read_sized_string, exception)
|
|
75
|
-
when "|" then
|
|
75
|
+
when "|" then read_attribute(exception)
|
|
76
76
|
else raise ProtocolError, "Unknown RESP type byte: #{type.inspect}"
|
|
77
77
|
end
|
|
78
78
|
rescue EOFError
|
|
@@ -94,18 +94,46 @@ module SolidRedis
|
|
|
94
94
|
length = Integer(read_line)
|
|
95
95
|
return if length == -1
|
|
96
96
|
|
|
97
|
-
Array.new(length) { read(exception:
|
|
97
|
+
finish_collection(Array.new(length) { read(exception: false) }, exception)
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
def read_collection(exception)
|
|
101
101
|
length = Integer(read_line)
|
|
102
|
-
Array.new(length) { read(exception:
|
|
102
|
+
finish_collection(Array.new(length) { read(exception: false) }, exception)
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
def read_map(exception)
|
|
106
106
|
length = Integer(read_line)
|
|
107
|
-
{}.tap do |
|
|
108
|
-
length.times {
|
|
107
|
+
map = {}.tap do |result|
|
|
108
|
+
length.times { result[read(exception: false)] = read(exception: false) }
|
|
109
|
+
end
|
|
110
|
+
finish_collection(map, exception)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def read_attribute(exception)
|
|
114
|
+
attributes = read_map(false)
|
|
115
|
+
value = read(exception: false)
|
|
116
|
+
raise_nested_error(attributes) if exception
|
|
117
|
+
raise_nested_error(value) if exception
|
|
118
|
+
value
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def finish_collection(value, exception)
|
|
122
|
+
raise_nested_error(value) if exception
|
|
123
|
+
value
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def raise_nested_error(value)
|
|
127
|
+
case value
|
|
128
|
+
when CommandError
|
|
129
|
+
raise value
|
|
130
|
+
when Array
|
|
131
|
+
value.each { |element| raise_nested_error(element) }
|
|
132
|
+
when Hash
|
|
133
|
+
value.each do |key, element|
|
|
134
|
+
raise_nested_error(key)
|
|
135
|
+
raise_nested_error(element)
|
|
136
|
+
end
|
|
109
137
|
end
|
|
110
138
|
end
|
|
111
139
|
|
|
@@ -140,9 +168,12 @@ module SolidRedis
|
|
|
140
168
|
end
|
|
141
169
|
|
|
142
170
|
def fill_buffer
|
|
171
|
+
wait_for = :readable
|
|
143
172
|
loop do
|
|
144
173
|
if @io.respond_to?(:to_io)
|
|
145
|
-
|
|
174
|
+
readers = wait_for == :readable ? [@io] : nil
|
|
175
|
+
writers = wait_for == :writable ? [@io] : nil
|
|
176
|
+
unless IO.select(readers, writers, nil, @read_timeout)
|
|
146
177
|
raise TimeoutError, "Redis read timed out after #{@read_timeout}s"
|
|
147
178
|
end
|
|
148
179
|
|
|
@@ -151,7 +182,10 @@ module SolidRedis
|
|
|
151
182
|
chunk = @io.read(16_384)
|
|
152
183
|
end
|
|
153
184
|
|
|
154
|
-
|
|
185
|
+
if chunk == :wait_readable || chunk == :wait_writable
|
|
186
|
+
wait_for = chunk == :wait_readable ? :readable : :writable
|
|
187
|
+
next
|
|
188
|
+
end
|
|
155
189
|
raise EOFError if chunk.nil?
|
|
156
190
|
|
|
157
191
|
@buffer << chunk
|
|
@@ -75,6 +75,9 @@ module SolidRedis
|
|
|
75
75
|
return unless @reader.wait_readable(timeout)
|
|
76
76
|
|
|
77
77
|
return decode(@reader.read)
|
|
78
|
+
rescue ProtocolError => error
|
|
79
|
+
handle_error(error)
|
|
80
|
+
raise
|
|
78
81
|
rescue ConnectionError, IO::WaitReadable, IO::WaitWritable, SystemCallError => error
|
|
79
82
|
handle_error(error)
|
|
80
83
|
raise error if attempts >= config.reconnect_attempts
|
|
@@ -123,6 +126,9 @@ module SolidRedis
|
|
|
123
126
|
loop do
|
|
124
127
|
ensure_connected
|
|
125
128
|
return write(RESP.encode(yield))
|
|
129
|
+
rescue ProtocolError => error
|
|
130
|
+
handle_error(error)
|
|
131
|
+
raise
|
|
126
132
|
rescue ConnectionError, IO::WaitReadable, IO::WaitWritable, SystemCallError => error
|
|
127
133
|
handle_error(error)
|
|
128
134
|
raise error if attempts >= config.reconnect_attempts
|
data/lib/solid_redis/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: solid-redis
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nicolas Vandenbogaerde
|
|
@@ -78,6 +78,7 @@ executables: []
|
|
|
78
78
|
extensions: []
|
|
79
79
|
extra_rdoc_files: []
|
|
80
80
|
files:
|
|
81
|
+
- CHANGELOG.md
|
|
81
82
|
- LICENSE.txt
|
|
82
83
|
- README.md
|
|
83
84
|
- lib/solid_redis.rb
|
|
@@ -103,8 +104,9 @@ licenses:
|
|
|
103
104
|
- MIT
|
|
104
105
|
metadata:
|
|
105
106
|
rubygems_mfa_required: 'true'
|
|
106
|
-
documentation_uri: https://www.rubydoc.info/gems/solid-redis/1.0.
|
|
107
|
+
documentation_uri: https://www.rubydoc.info/gems/solid-redis/1.0.3
|
|
107
108
|
source_code_uri: https://github.com/nicolasva/solid-redis
|
|
109
|
+
changelog_uri: https://github.com/nicolasva/solid-redis/blob/main/CHANGELOG.md
|
|
108
110
|
rdoc_options: []
|
|
109
111
|
require_paths:
|
|
110
112
|
- lib
|