Skip to content

Commit 826de61

Browse files
committed
Improve redis-client error translation
Automatically handle subclasses, useful for CommandError for instance.
1 parent d180452 commit 826de61

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

.rubocop.yml

+3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ Style/NumericPredicate:
6868
Style/IfUnlessModifier:
6969
Enabled: false
7070

71+
Style/MutableConstant:
72+
Enabled: false # false positives
73+
7174
Style/SignalException:
7275
Exclude:
7376
- 'lib/redis/connection/synchrony.rb'

lib/redis/client.rb

+20-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class Client < ::RedisClient
1515
RedisClient::WrongTypeError => Redis::WrongTypeError,
1616
RedisClient::ReadOnlyError => Redis::ReadOnlyError,
1717
RedisClient::ProtocolError => Redis::ProtocolError,
18-
}.freeze
18+
}
1919

2020
class << self
2121
def config(**kwargs)
@@ -78,7 +78,7 @@ def password
7878
def call_v(command, &block)
7979
super(command, &block)
8080
rescue ::RedisClient::Error => error
81-
raise ERROR_MAPPING.fetch(error.class), error.message, error.backtrace
81+
translate_error!(error)
8282
end
8383

8484
def blocking_call_v(timeout, command, &block)
@@ -91,19 +91,19 @@ def blocking_call_v(timeout, command, &block)
9191

9292
super(timeout, command, &block)
9393
rescue ::RedisClient::Error => error
94-
raise ERROR_MAPPING.fetch(error.class), error.message, error.backtrace
94+
translate_error!(error)
9595
end
9696

9797
def pipelined
9898
super
9999
rescue ::RedisClient::Error => error
100-
raise ERROR_MAPPING.fetch(error.class), error.message, error.backtrace
100+
translate_error!(error)
101101
end
102102

103103
def multi
104104
super
105105
rescue ::RedisClient::Error => error
106-
raise ERROR_MAPPING.fetch(error.class), error.message, error.backtrace
106+
translate_error!(error)
107107
end
108108

109109
def disable_reconnection(&block)
@@ -121,6 +121,21 @@ def close
121121

122122
private
123123

124+
def translate_error!(error)
125+
redis_error = translate_error_class(error.class)
126+
raise redis_error, error.message, error.backtrace
127+
end
128+
129+
def translate_error_class(error_class)
130+
ERROR_MAPPING.fetch(error_class)
131+
rescue IndexError
132+
if (client_error = error_class.ancestors.find { |a| ERROR_MAPPING[a] })
133+
ERROR_MAPPING[error_class] = ERROR_MAPPING[client_error]
134+
else
135+
raise
136+
end
137+
end
138+
124139
def ensure_connected(retryable: true)
125140
unless @inherit_socket || (@pid ||= Process.pid) == Process.pid
126141
raise InheritedError,

test/redis/client_test.rb

+9
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ def test_call_raise
2626
end
2727
end
2828

29+
def test_error_translate_subclasses
30+
error = Class.new(RedisClient::CommandError)
31+
assert_equal Redis::CommandError, r._client.send(:translate_error_class, error)
32+
33+
assert_raises KeyError do
34+
r._client.send(:translate_error_class, StandardError)
35+
end
36+
end
37+
2938
def test_mixed_encoding
3039
r.call("MSET", "fée", "\x00\xFF".b, "じ案".encode(Encoding::SHIFT_JIS), "\t".encode(Encoding::ASCII))
3140
assert_equal "\x00\xFF".b, r.call("GET", "fée")

0 commit comments

Comments
 (0)