Skip to content

Commit baf8d64

Browse files
committed
Merge branch 'beedub-write_timeout' into 3.3
2 parents c1f6a58 + 45ccba4 commit baf8d64

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

lib/redis/client.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Client
1313
:path => nil,
1414
:timeout => 5.0,
1515
:connect_timeout => 5.0,
16+
:write_timeout => nil,
1617
:password => nil,
1718
:db => 0,
1819
:driver => nil,
@@ -433,6 +434,8 @@ def _parse_options(options)
433434
options[:timeout]
434435
end
435436

437+
options[:write_timeout] = options[:write_timeout] ? options[:write_timeout].to_f : options[:timeout]
438+
436439
options[:db] = options[:db].to_i
437440
options[:driver] = _parse_driver(options[:driver]) || Connection.drivers.last
438441

lib/redis/connection/ruby.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require "redis/connection/command_helper"
33
require "redis/errors"
44
require "socket"
5+
require "timeout"
56

67
class Redis
78
module Connection
@@ -12,7 +13,7 @@ module SocketMixin
1213
def initialize(*args)
1314
super(*args)
1415

15-
@timeout = nil
16+
@timeout = @write_timeout = nil
1617
@buffer = ""
1718
end
1819

@@ -24,6 +25,14 @@ def timeout=(timeout)
2425
end
2526
end
2627

28+
def write_timeout=(timeout)
29+
if timeout && timeout > 0
30+
@write_timeout = timeout
31+
else
32+
@write_timeout = nil
33+
end
34+
end
35+
2736
def read(nbytes)
2837
result = @buffer.slice!(0, nbytes)
2938

@@ -59,6 +68,11 @@ def _read_from_socket(nbytes)
5968
rescue EOFError
6069
raise Errno::ECONNRESET
6170
end
71+
72+
# UNIXSocket and TCPSocket don't support write timeouts
73+
def write(*args)
74+
Timeout.timeout(@write_timeout, TimeoutError) { super }
75+
end
6276
end
6377

6478
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
@@ -213,6 +227,7 @@ def self.connect(config)
213227

214228
instance = new(sock)
215229
instance.timeout = config[:timeout]
230+
instance.write_timeout = config[:write_timeout]
216231
instance.set_tcp_keepalive config[:tcp_keepalive]
217232
instance
218233
end
@@ -265,6 +280,10 @@ def timeout=(timeout)
265280
end
266281
end
267282

283+
def write_timeout=(timeout)
284+
@sock.write_timeout = timeout
285+
end
286+
268287
def write(command)
269288
@sock.write(build_command(command))
270289
end

test/internals_test.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,19 @@ def test_connection_timeout
160160
assert (Time.now - start_time) <= opts[:timeout]
161161
end
162162

163+
driver(:ruby) do
164+
def test_write_timeout
165+
TCPServer.new("127.0.0.1", 6383)
166+
167+
assert_raise(Redis::TimeoutError) do
168+
Timeout.timeout(1) do
169+
redis = Redis.new(:port => 6383, :timeout => 5, :write_timeout => 0.2)
170+
redis.set("foo", "1" * 1048576)
171+
end
172+
end
173+
end
174+
end
175+
163176
def close_on_ping(seq, options = {})
164177
$request = 0
165178

test/lint/blocking_commands.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def mock(options = {}, &blk)
3535
:brpoplpush => lambda do |*args|
3636
sleep options[:delay] if options.has_key?(:delay)
3737
to_protocol(args.last)
38-
end,
38+
end
3939
}
4040

4141
redis_mock(commands, &blk)

0 commit comments

Comments
 (0)