redis 4.0.0.rc1 → 4.5.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.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +164 -3
  3. data/README.md +127 -18
  4. data/lib/redis/client.rb +164 -93
  5. data/lib/redis/cluster/command.rb +81 -0
  6. data/lib/redis/cluster/command_loader.rb +33 -0
  7. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  8. data/lib/redis/cluster/node.rb +108 -0
  9. data/lib/redis/cluster/node_key.rb +31 -0
  10. data/lib/redis/cluster/node_loader.rb +37 -0
  11. data/lib/redis/cluster/option.rb +93 -0
  12. data/lib/redis/cluster/slot.rb +86 -0
  13. data/lib/redis/cluster/slot_loader.rb +49 -0
  14. data/lib/redis/cluster.rb +291 -0
  15. data/lib/redis/connection/command_helper.rb +5 -2
  16. data/lib/redis/connection/hiredis.rb +4 -3
  17. data/lib/redis/connection/registry.rb +2 -1
  18. data/lib/redis/connection/ruby.rb +125 -106
  19. data/lib/redis/connection/synchrony.rb +18 -5
  20. data/lib/redis/connection.rb +2 -0
  21. data/lib/redis/distributed.rb +995 -0
  22. data/lib/redis/errors.rb +48 -0
  23. data/lib/redis/hash_ring.rb +89 -0
  24. data/lib/redis/pipeline.rb +55 -9
  25. data/lib/redis/subscribe.rb +11 -12
  26. data/lib/redis/version.rb +3 -1
  27. data/lib/redis.rb +1433 -381
  28. metadata +34 -141
  29. data/.gitignore +0 -16
  30. data/.travis/Gemfile +0 -11
  31. data/.travis.yml +0 -71
  32. data/.yardopts +0 -3
  33. data/Gemfile +0 -3
  34. data/benchmarking/logging.rb +0 -71
  35. data/benchmarking/pipeline.rb +0 -51
  36. data/benchmarking/speed.rb +0 -21
  37. data/benchmarking/suite.rb +0 -24
  38. data/benchmarking/worker.rb +0 -71
  39. data/examples/basic.rb +0 -15
  40. data/examples/consistency.rb +0 -114
  41. data/examples/incr-decr.rb +0 -17
  42. data/examples/list.rb +0 -26
  43. data/examples/pubsub.rb +0 -37
  44. data/examples/sentinel/sentinel.conf +0 -9
  45. data/examples/sentinel/start +0 -49
  46. data/examples/sentinel.rb +0 -41
  47. data/examples/sets.rb +0 -36
  48. data/examples/unicorn/config.ru +0 -3
  49. data/examples/unicorn/unicorn.rb +0 -20
  50. data/makefile +0 -42
  51. data/redis.gemspec +0 -40
  52. data/test/bitpos_test.rb +0 -63
  53. data/test/blocking_commands_test.rb +0 -183
  54. data/test/client_test.rb +0 -59
  55. data/test/command_map_test.rb +0 -28
  56. data/test/commands_on_hashes_test.rb +0 -174
  57. data/test/commands_on_hyper_log_log_test.rb +0 -70
  58. data/test/commands_on_lists_test.rb +0 -154
  59. data/test/commands_on_sets_test.rb +0 -208
  60. data/test/commands_on_sorted_sets_test.rb +0 -444
  61. data/test/commands_on_strings_test.rb +0 -338
  62. data/test/commands_on_value_types_test.rb +0 -246
  63. data/test/connection_handling_test.rb +0 -275
  64. data/test/db/.gitkeep +0 -0
  65. data/test/encoding_test.rb +0 -14
  66. data/test/error_replies_test.rb +0 -57
  67. data/test/fork_safety_test.rb +0 -60
  68. data/test/helper.rb +0 -179
  69. data/test/helper_test.rb +0 -22
  70. data/test/internals_test.rb +0 -435
  71. data/test/persistence_control_commands_test.rb +0 -24
  72. data/test/pipelining_commands_test.rb +0 -238
  73. data/test/publish_subscribe_test.rb +0 -280
  74. data/test/remote_server_control_commands_test.rb +0 -175
  75. data/test/scanning_test.rb +0 -407
  76. data/test/scripting_test.rb +0 -76
  77. data/test/sentinel_command_test.rb +0 -78
  78. data/test/sentinel_test.rb +0 -253
  79. data/test/sorting_test.rb +0 -57
  80. data/test/ssl_test.rb +0 -69
  81. data/test/support/connection/hiredis.rb +0 -1
  82. data/test/support/connection/ruby.rb +0 -1
  83. data/test/support/connection/synchrony.rb +0 -17
  84. data/test/support/redis_mock.rb +0 -130
  85. data/test/support/ssl/gen_certs.sh +0 -31
  86. data/test/support/ssl/trusted-ca.crt +0 -25
  87. data/test/support/ssl/trusted-ca.key +0 -27
  88. data/test/support/ssl/trusted-cert.crt +0 -81
  89. data/test/support/ssl/trusted-cert.key +0 -28
  90. data/test/support/ssl/untrusted-ca.crt +0 -26
  91. data/test/support/ssl/untrusted-ca.key +0 -27
  92. data/test/support/ssl/untrusted-cert.crt +0 -82
  93. data/test/support/ssl/untrusted-cert.key +0 -28
  94. data/test/support/wire/synchrony.rb +0 -24
  95. data/test/support/wire/thread.rb +0 -5
  96. data/test/synchrony_driver.rb +0 -85
  97. data/test/test.conf.erb +0 -9
  98. data/test/thread_safety_test.rb +0 -60
  99. data/test/transactions_test.rb +0 -262
  100. data/test/unknown_commands_test.rb +0 -12
  101. data/test/url_param_test.rb +0 -136
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Redis
2
4
  module Connection
3
5
  module CommandHelper
4
-
5
6
  COMMAND_DELIMITER = "\r\n"
6
7
 
7
8
  def build_command(args)
@@ -11,11 +12,13 @@ class Redis
11
12
  if i.is_a? Array
12
13
  i.each do |j|
13
14
  j = j.to_s
15
+ j = j.encoding == Encoding::BINARY ? j : j.b
14
16
  command << "$#{j.bytesize}"
15
17
  command << j
16
18
  end
17
19
  else
18
20
  i = i.to_s
21
+ i = i.encoding == Encoding::BINARY ? i : i.b
19
22
  command << "$#{i.bytesize}"
20
23
  command << i
21
24
  end
@@ -28,7 +31,7 @@ class Redis
28
31
  command.join(COMMAND_DELIMITER)
29
32
  end
30
33
 
31
- protected
34
+ protected
32
35
 
33
36
  def encode(string)
34
37
  string.force_encoding(Encoding.default_external)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "registry"
2
4
  require_relative "../errors"
3
5
  require "hiredis/connection"
@@ -6,7 +8,6 @@ require "timeout"
6
8
  class Redis
7
9
  module Connection
8
10
  class Hiredis
9
-
10
11
  def self.connect(config)
11
12
  connection = ::Hiredis::Connection.new
12
13
  connect_timeout = (config.fetch(:connect_timeout, 0) * 1_000_000).to_i
@@ -31,7 +32,7 @@ class Redis
31
32
  end
32
33
 
33
34
  def connected?
34
- @connection && @connection.connected?
35
+ @connection&.connected?
35
36
  end
36
37
 
37
38
  def timeout=(timeout)
@@ -57,7 +58,7 @@ class Redis
57
58
  rescue Errno::EAGAIN
58
59
  raise TimeoutError
59
60
  rescue RuntimeError => err
60
- raise ProtocolError.new(err.message)
61
+ raise ProtocolError, err.message
61
62
  end
62
63
  end
63
64
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Redis
2
4
  module Connection
3
-
4
5
  # Store a list of loaded connection drivers in the Connection module.
5
6
  # Redis::Client uses the last required driver by default, and will be aware
6
7
  # of the loaded connection drivers if the user chooses to override the
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "registry"
2
4
  require_relative "command_helper"
3
5
  require_relative "../errors"
@@ -13,108 +15,85 @@ end
13
15
  class Redis
14
16
  module Connection
15
17
  module SocketMixin
16
-
17
- CRLF = "\r\n".freeze
18
+ CRLF = "\r\n"
18
19
 
19
20
  def initialize(*args)
20
21
  super(*args)
21
22
 
22
23
  @timeout = @write_timeout = nil
23
- @buffer = ""
24
+ @buffer = "".b
24
25
  end
25
26
 
26
27
  def timeout=(timeout)
27
- if timeout && timeout > 0
28
- @timeout = timeout
29
- else
30
- @timeout = nil
31
- end
28
+ @timeout = (timeout if timeout && timeout > 0)
32
29
  end
33
30
 
34
31
  def write_timeout=(timeout)
35
- if timeout && timeout > 0
36
- @write_timeout = timeout
37
- else
38
- @write_timeout = nil
39
- end
32
+ @write_timeout = (timeout if timeout && timeout > 0)
40
33
  end
41
34
 
42
35
  def read(nbytes)
43
36
  result = @buffer.slice!(0, nbytes)
44
37
 
45
- while result.bytesize < nbytes
46
- result << _read_from_socket(nbytes - result.bytesize)
47
- end
38
+ buffer = String.new(capacity: nbytes, encoding: Encoding::ASCII_8BIT)
39
+ result << _read_from_socket(nbytes - result.bytesize, buffer) while result.bytesize < nbytes
48
40
 
49
41
  result
50
42
  end
51
43
 
52
44
  def gets
53
- crlf = nil
54
-
55
- while (crlf = @buffer.index(CRLF)) == nil
56
- @buffer << _read_from_socket(1024)
45
+ while (crlf = @buffer.index(CRLF)).nil?
46
+ @buffer << _read_from_socket(16_384)
57
47
  end
58
48
 
59
49
  @buffer.slice!(0, crlf + CRLF.bytesize)
60
50
  end
61
51
 
62
- def _read_from_socket(nbytes)
63
-
64
- begin
65
- read_nonblock(nbytes)
66
-
67
- rescue IO::WaitReadable
68
- if IO.select([self], nil, nil, @timeout)
69
- retry
70
- else
71
- raise Redis::TimeoutError
72
- end
73
- rescue IO::WaitWritable
74
- if IO.select(nil, [self], nil, @timeout)
75
- retry
76
- else
77
- raise Redis::TimeoutError
78
- end
79
- end
80
-
81
- rescue EOFError
82
- raise Errno::ECONNRESET
83
- end
84
-
85
- def _write_to_socket(data)
86
- begin
87
- write_nonblock(data)
88
-
89
- rescue IO::WaitWritable
90
- if IO.select(nil, [self], nil, @write_timeout)
91
- retry
92
- else
93
- raise Redis::TimeoutError
94
- end
95
- rescue IO::WaitReadable
96
- if IO.select([self], nil, nil, @write_timeout)
97
- retry
98
- else
99
- raise Redis::TimeoutError
52
+ def _read_from_socket(nbytes, buffer = nil)
53
+ loop do
54
+ case chunk = read_nonblock(nbytes, buffer, exception: false)
55
+ when :wait_readable
56
+ unless wait_readable(@timeout)
57
+ raise Redis::TimeoutError
58
+ end
59
+ when :wait_writable
60
+ unless wait_writable(@timeout)
61
+ raise Redis::TimeoutError
62
+ end
63
+ when nil
64
+ raise Errno::ECONNRESET
65
+ when String
66
+ return chunk
100
67
  end
101
68
  end
102
-
103
- rescue EOFError
104
- raise Errno::ECONNRESET
105
69
  end
106
70
 
107
- def write(data)
108
- return super(data) unless @write_timeout
71
+ def write(buffer)
72
+ return super(buffer) unless @write_timeout
109
73
 
110
- length = data.bytesize
111
- total_count = 0
74
+ bytes_to_write = buffer.bytesize
75
+ total_bytes_written = 0
112
76
  loop do
113
- count = _write_to_socket(data)
77
+ case bytes_written = write_nonblock(buffer, exception: false)
78
+ when :wait_readable
79
+ unless wait_readable(@write_timeout)
80
+ raise Redis::TimeoutError
81
+ end
82
+ when :wait_writable
83
+ unless wait_writable(@write_timeout)
84
+ raise Redis::TimeoutError
85
+ end
86
+ when nil
87
+ raise Errno::ECONNRESET
88
+ when Integer
89
+ total_bytes_written += bytes_written
90
+
91
+ if total_bytes_written >= bytes_to_write
92
+ return total_bytes_written
93
+ end
114
94
 
115
- total_count += count
116
- return total_count if total_count >= length
117
- data = data.byteslice(count..-1)
95
+ buffer = buffer.byteslice(bytes_written..-1)
96
+ end
118
97
  end
119
98
  end
120
99
  end
@@ -124,7 +103,6 @@ class Redis
124
103
  require "timeout"
125
104
 
126
105
  class TCPSocket < ::TCPSocket
127
-
128
106
  include SocketMixin
129
107
 
130
108
  def self.connect(host, port, timeout)
@@ -140,7 +118,6 @@ class Redis
140
118
  if defined?(::UNIXSocket)
141
119
 
142
120
  class UNIXSocket < ::UNIXSocket
143
-
144
121
  include SocketMixin
145
122
 
146
123
  def self.connect(path, timeout)
@@ -152,13 +129,12 @@ class Redis
152
129
  raise TimeoutError
153
130
  end
154
131
 
155
- # JRuby raises Errno::EAGAIN on #read_nonblock even when IO.select
132
+ # JRuby raises Errno::EAGAIN on #read_nonblock even when it
156
133
  # says it is readable (1.6.6, in both 1.8 and 1.9 mode).
157
134
  # Use the blocking #readpartial method instead.
158
135
 
159
136
  def _read_from_socket(nbytes)
160
137
  readpartial(nbytes)
161
-
162
138
  rescue EOFError
163
139
  raise Errno::ECONNRESET
164
140
  end
@@ -169,19 +145,16 @@ class Redis
169
145
  else
170
146
 
171
147
  class TCPSocket < ::Socket
172
-
173
148
  include SocketMixin
174
149
 
175
- def self.connect_addrinfo(ai, port, timeout)
176
- sock = new(::Socket.const_get(ai[0]), Socket::SOCK_STREAM, 0)
177
- sockaddr = ::Socket.pack_sockaddr_in(port, ai[3])
150
+ def self.connect_addrinfo(addrinfo, port, timeout)
151
+ sock = new(::Socket.const_get(addrinfo[0]), Socket::SOCK_STREAM, 0)
152
+ sockaddr = ::Socket.pack_sockaddr_in(port, addrinfo[3])
178
153
 
179
154
  begin
180
155
  sock.connect_nonblock(sockaddr)
181
156
  rescue Errno::EINPROGRESS
182
- if IO.select(nil, [sock], nil, timeout) == nil
183
- raise TimeoutError
184
- end
157
+ raise TimeoutError unless sock.wait_writable(timeout)
185
158
 
186
159
  begin
187
160
  sock.connect_nonblock(sockaddr)
@@ -220,14 +193,13 @@ class Redis
220
193
  return connect_addrinfo(ai, port, timeout)
221
194
  rescue SystemCallError
222
195
  # Raise if this was our last attempt.
223
- raise if addrinfo.length == i+1
196
+ raise if addrinfo.length == i + 1
224
197
  end
225
198
  end
226
199
  end
227
200
  end
228
201
 
229
202
  class UNIXSocket < ::Socket
230
-
231
203
  include SocketMixin
232
204
 
233
205
  def self.connect(path, timeout)
@@ -237,9 +209,7 @@ class Redis
237
209
  begin
238
210
  sock.connect_nonblock(sockaddr)
239
211
  rescue Errno::EINPROGRESS
240
- if IO.select(nil, [sock], nil, timeout) == nil
241
- raise TimeoutError
242
- end
212
+ raise TimeoutError unless sock.wait_writable(timeout)
243
213
 
244
214
  begin
245
215
  sock.connect_nonblock(sockaddr)
@@ -257,17 +227,58 @@ class Redis
257
227
  class SSLSocket < ::OpenSSL::SSL::SSLSocket
258
228
  include SocketMixin
259
229
 
230
+ unless method_defined?(:wait_readable)
231
+ def wait_readable(timeout = nil)
232
+ to_io.wait_readable(timeout)
233
+ end
234
+ end
235
+
236
+ unless method_defined?(:wait_writable)
237
+ def wait_writable(timeout = nil)
238
+ to_io.wait_writable(timeout)
239
+ end
240
+ end
241
+
260
242
  def self.connect(host, port, timeout, ssl_params)
261
243
  # Note: this is using Redis::Connection::TCPSocket
262
244
  tcp_sock = TCPSocket.connect(host, port, timeout)
263
245
 
264
246
  ctx = OpenSSL::SSL::SSLContext.new
265
- ctx.set_params(ssl_params) if ssl_params && !ssl_params.empty?
247
+
248
+ # The provided parameters are merged into OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
249
+ ctx.set_params(ssl_params || {})
266
250
 
267
251
  ssl_sock = new(tcp_sock, ctx)
268
252
  ssl_sock.hostname = host
269
- ssl_sock.connect
270
- ssl_sock.post_connection_check(host)
253
+
254
+ begin
255
+ # Initiate the socket connection in the background. If it doesn't fail
256
+ # immediately it will raise an IO::WaitWritable (Errno::EINPROGRESS)
257
+ # indicating the connection is in progress.
258
+ # Unlike waiting for a tcp socket to connect, you can't time out ssl socket
259
+ # connections during the connect phase properly, because IO.select only partially works.
260
+ # Instead, you have to retry.
261
+ ssl_sock.connect_nonblock
262
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
263
+ if ssl_sock.wait_readable(timeout)
264
+ retry
265
+ else
266
+ raise TimeoutError
267
+ end
268
+ rescue IO::WaitWritable
269
+ if ssl_sock.wait_writable(timeout)
270
+ retry
271
+ else
272
+ raise TimeoutError
273
+ end
274
+ end
275
+
276
+ unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
277
+ ctx.respond_to?(:verify_hostname) &&
278
+ !ctx.verify_hostname
279
+ )
280
+ ssl_sock.post_connection_check(host)
281
+ end
271
282
 
272
283
  ssl_sock
273
284
  end
@@ -277,15 +288,16 @@ class Redis
277
288
  class Ruby
278
289
  include Redis::Connection::CommandHelper
279
290
 
280
- MINUS = "-".freeze
281
- PLUS = "+".freeze
282
- COLON = ":".freeze
283
- DOLLAR = "$".freeze
284
- ASTERISK = "*".freeze
291
+ MINUS = "-"
292
+ PLUS = "+"
293
+ COLON = ":"
294
+ DOLLAR = "$"
295
+ ASTERISK = "*"
285
296
 
286
297
  def self.connect(config)
287
298
  if config[:scheme] == "unix"
288
299
  raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl]
300
+
289
301
  sock = UNIXSocket.connect(config[:path], config[:connect_timeout])
290
302
  elsif config[:scheme] == "rediss" || config[:ssl]
291
303
  sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params])
@@ -294,13 +306,14 @@ class Redis
294
306
  end
295
307
 
296
308
  instance = new(sock)
297
- instance.timeout = config[:timeout]
309
+ instance.timeout = config[:read_timeout]
298
310
  instance.write_timeout = config[:write_timeout]
299
311
  instance.set_tcp_keepalive config[:tcp_keepalive]
312
+ instance.set_tcp_nodelay if sock.is_a? TCPSocket
300
313
  instance
301
314
  end
302
315
 
303
- if [:SOL_SOCKET, :SO_KEEPALIVE, :SOL_TCP, :TCP_KEEPIDLE, :TCP_KEEPINTVL, :TCP_KEEPCNT].all?{|c| Socket.const_defined? c}
316
+ if %i[SOL_SOCKET SO_KEEPALIVE SOL_TCP TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT].all? { |c| Socket.const_defined? c }
304
317
  def set_tcp_keepalive(keepalive)
305
318
  return unless keepalive.is_a?(Hash)
306
319
 
@@ -312,14 +325,13 @@ class Redis
312
325
 
313
326
  def get_tcp_keepalive
314
327
  {
315
- :time => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
316
- :intvl => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
317
- :probes => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int,
328
+ time: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
329
+ intvl: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
330
+ probes: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int
318
331
  }
319
332
  end
320
333
  else
321
- def set_tcp_keepalive(keepalive)
322
- end
334
+ def set_tcp_keepalive(keepalive); end
323
335
 
324
336
  def get_tcp_keepalive
325
337
  {
@@ -327,12 +339,21 @@ class Redis
327
339
  end
328
340
  end
329
341
 
342
+ # disables Nagle's Algorithm, prevents multiple round trips with MULTI
343
+ if %i[IPPROTO_TCP TCP_NODELAY].all? { |c| Socket.const_defined? c }
344
+ def set_tcp_nodelay
345
+ @sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
346
+ end
347
+ else
348
+ def set_tcp_nodelay; end
349
+ end
350
+
330
351
  def initialize(sock)
331
352
  @sock = sock
332
353
  end
333
354
 
334
355
  def connected?
335
- !! @sock
356
+ !!@sock
336
357
  end
337
358
 
338
359
  def disconnect
@@ -343,9 +364,7 @@ class Redis
343
364
  end
344
365
 
345
366
  def timeout=(timeout)
346
- if @sock.respond_to?(:timeout=)
347
- @sock.timeout = timeout
348
- end
367
+ @sock.timeout = timeout if @sock.respond_to?(:timeout=)
349
368
  end
350
369
 
351
370
  def write_timeout=(timeout)
@@ -360,7 +379,6 @@ class Redis
360
379
  line = @sock.gets
361
380
  reply_type = line.slice!(0, 1)
362
381
  format_reply(reply_type, line)
363
-
364
382
  rescue Errno::EAGAIN
365
383
  raise TimeoutError
366
384
  end
@@ -372,7 +390,7 @@ class Redis
372
390
  when COLON then format_integer_reply(line)
373
391
  when DOLLAR then format_bulk_reply(line)
374
392
  when ASTERISK then format_multi_bulk_reply(line)
375
- else raise ProtocolError.new(reply_type)
393
+ else raise ProtocolError, reply_type
376
394
  end
377
395
  end
378
396
 
@@ -391,6 +409,7 @@ class Redis
391
409
  def format_bulk_reply(line)
392
410
  bulklen = line.to_i
393
411
  return if bulklen == -1
412
+
394
413
  reply = encode(@sock.read(bulklen))
395
414
  @sock.read(2) # Discard CRLF.
396
415
  reply
@@ -1,9 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "command_helper"
2
4
  require_relative "registry"
3
5
  require_relative "../errors"
4
6
  require "em-synchrony"
5
7
  require "hiredis/reader"
6
8
 
9
+ Kernel.warn(
10
+ "The redis synchrony driver is deprecated and will be removed in redis-rb 5.0. " \
11
+ "We're looking for people to maintain it as a separate gem, see https://github.com/redis/redis-rb/issues/915"
12
+ )
13
+
7
14
  class Redis
8
15
  module Connection
9
16
  class RedisClient < EventMachine::Connection
@@ -46,9 +53,7 @@ class Redis
46
53
 
47
54
  def read
48
55
  @req = EventMachine::DefaultDeferrable.new
49
- if @timeout > 0
50
- @req.timeout(@timeout, :timeout)
51
- end
56
+ @req.timeout(@timeout, :timeout) if @timeout > 0
52
57
  EventMachine::Synchrony.sync @req
53
58
  end
54
59
 
@@ -72,7 +77,15 @@ class Redis
72
77
 
73
78
  def self.connect(config)
74
79
  if config[:scheme] == "unix"
75
- conn = EventMachine.connect_unix_domain(config[:path], RedisClient)
80
+ begin
81
+ conn = EventMachine.connect_unix_domain(config[:path], RedisClient)
82
+ rescue RuntimeError => e
83
+ if e.message == "no connection"
84
+ raise Errno::ECONNREFUSED
85
+ else
86
+ raise e
87
+ end
88
+ end
76
89
  elsif config[:scheme] == "rediss" || config[:ssl]
77
90
  raise NotImplementedError, "SSL not supported by synchrony driver"
78
91
  else
@@ -97,7 +110,7 @@ class Redis
97
110
  end
98
111
 
99
112
  def connected?
100
- @connection && @connection.connected?
113
+ @connection&.connected?
101
114
  end
102
115
 
103
116
  def timeout=(timeout)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "connection/registry"
2
4
 
3
5
  # If a connection driver was required before this file, the array