Skip to content

Commit 6737893

Browse files
committed
Fix inconsistent connections when using Timeout under MRI 2.1+.
1 parent d9f5899 commit 6737893

File tree

5 files changed

+35
-1
lines changed

5 files changed

+35
-1
lines changed

lib/redis/client.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,10 @@ def ensure_connected
342342
connect
343343
end
344344

345-
yield
345+
connection.use { yield }
346+
rescue ConnectionCorruptedError
347+
disconnect
348+
retry
346349
rescue BaseConnectionError
347350
disconnect
348351

lib/redis/connection/hiredis.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ def read
5656
rescue RuntimeError => err
5757
raise ProtocolError.new(err.message)
5858
end
59+
60+
def use
61+
yield
62+
end
5963
end
6064
end
6165
end

lib/redis/connection/ruby.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ def get_tcp_keepalive
246246

247247
def initialize(sock)
248248
@sock = sock
249+
@pending_reads = 0
249250
end
250251

251252
def connected?
@@ -266,6 +267,7 @@ def timeout=(timeout)
266267
end
267268

268269
def write(command)
270+
@pending_reads += 1
269271
@sock.write(build_command(command))
270272
end
271273

@@ -290,18 +292,22 @@ def format_reply(reply_type, line)
290292
end
291293

292294
def format_error_reply(line)
295+
@pending_reads -= 1
293296
CommandError.new(line.strip)
294297
end
295298

296299
def format_status_reply(line)
300+
@pending_reads -= 1
297301
line.strip
298302
end
299303

300304
def format_integer_reply(line)
305+
@pending_reads -= 1
301306
line.to_i
302307
end
303308

304309
def format_bulk_reply(line)
310+
@pending_reads -= 1
305311
bulklen = line.to_i
306312
return if bulklen == -1
307313
reply = encode(@sock.read(bulklen))
@@ -311,10 +317,20 @@ def format_bulk_reply(line)
311317

312318
def format_multi_bulk_reply(line)
313319
n = line.to_i
320+
321+
@pending_reads += n
322+
314323
return if n == -1
315324

325+
@pending_reads -= 1
326+
316327
Array.new(n) { read }
317328
end
329+
330+
def use
331+
raise ConnectionCorruptedError if @pending_reads > 0
332+
yield
333+
end
318334
end
319335
end
320336
end

lib/redis/connection/synchrony.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ def read
117117
raise "Unknown type #{type.inspect}"
118118
end
119119
end
120+
121+
def use
122+
yield
123+
end
120124
end
121125
end
122126
end

lib/redis/errors.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,11 @@ class TimeoutError < BaseConnectionError
3737
# Raised when the connection was inherited by a child process.
3838
class InheritedError < BaseConnectionError
3939
end
40+
41+
# Raised when the connection is left in an inconsistent state
42+
# due to timeout issues. See issue #501.
43+
#
44+
# Only used internally.
45+
class ConnectionCorruptedError < BaseConnectionError
46+
end
4047
end

0 commit comments

Comments
 (0)