File tree Expand file tree Collapse file tree 4 files changed +47
-2
lines changed Expand file tree Collapse file tree 4 files changed +47
-2
lines changed Original file line number Diff line number Diff line change @@ -13,6 +13,7 @@ class Client
13
13
:path => nil ,
14
14
:timeout => 5.0 ,
15
15
:connect_timeout => 5.0 ,
16
+ :write_timeout => nil ,
16
17
:password => nil ,
17
18
:db => 0 ,
18
19
:driver => nil ,
@@ -419,6 +420,8 @@ def _parse_options(options)
419
420
options [ :timeout ]
420
421
end
421
422
423
+ options [ :write_timeout ] = options [ :write_timeout ] ? options [ :write_timeout ] . to_f : options [ :timeout ]
424
+
422
425
options [ :db ] = options [ :db ] . to_i
423
426
options [ :driver ] = _parse_driver ( options [ :driver ] ) || Connection . drivers . last
424
427
Original file line number Diff line number Diff line change @@ -12,7 +12,7 @@ module SocketMixin
12
12
def initialize ( *args )
13
13
super ( *args )
14
14
15
- @timeout = nil
15
+ @timeout = @write_timeout = nil
16
16
@buffer = ""
17
17
end
18
18
@@ -24,6 +24,14 @@ def timeout=(timeout)
24
24
end
25
25
end
26
26
27
+ def write_timeout = ( timeout )
28
+ if timeout && timeout > 0
29
+ @write_timeout = timeout
30
+ else
31
+ @write_timeout = nil
32
+ end
33
+ end
34
+
27
35
def read ( nbytes )
28
36
result = @buffer . slice! ( 0 , nbytes )
29
37
@@ -59,6 +67,11 @@ def _read_from_socket(nbytes)
59
67
rescue EOFError
60
68
raise Errno ::ECONNRESET
61
69
end
70
+
71
+ # UNIXSocket and TCPSocket don't support write timeouts
72
+ def write ( *args )
73
+ Timeout . timeout ( @write_timeout , TimeoutError ) { super }
74
+ end
62
75
end
63
76
64
77
if defined? ( RUBY_ENGINE ) && RUBY_ENGINE == "jruby"
@@ -213,6 +226,7 @@ def self.connect(config)
213
226
214
227
instance = new ( sock )
215
228
instance . timeout = config [ :timeout ]
229
+ instance . write_timeout = config [ :write_timeout ]
216
230
instance . set_tcp_keepalive config [ :tcp_keepalive ]
217
231
instance
218
232
end
@@ -265,6 +279,10 @@ def timeout=(timeout)
265
279
end
266
280
end
267
281
282
+ def write_timeout = ( timeout )
283
+ @sock . write_timeout = timeout
284
+ end
285
+
268
286
def write ( command )
269
287
@sock . write ( build_command ( command ) )
270
288
end
Original file line number Diff line number Diff line change @@ -160,6 +160,30 @@ def test_connection_timeout
160
160
assert ( Time . now - start_time ) <= opts [ :timeout ]
161
161
end
162
162
163
+ driver ( :ruby ) do
164
+ def test_write_timeout
165
+ redis_mock ( :write_timeout => 0.1 , :timeout => 1 ) do |redis |
166
+ # This is really disgusting, but this essentially mocks the "super" call in write
167
+ IO . class_eval do
168
+ alias_method :old_write , :write
169
+
170
+ def write ( *args )
171
+ sleep 1
172
+ end
173
+ end
174
+ assert_raise Redis ::TimeoutError do
175
+ redis . rpush ( "tmp" , "test" )
176
+ end
177
+ end
178
+ ensure
179
+ IO . class_eval do
180
+ undef_method :write
181
+ alias_method :write , :old_write
182
+ undef_method :old_write
183
+ end
184
+ end
185
+ end
186
+
163
187
def close_on_ping ( seq , options = { } )
164
188
$request = 0
165
189
Original file line number Diff line number Diff line change @@ -35,7 +35,7 @@ def mock(options = {}, &blk)
35
35
:brpoplpush => lambda do |*args |
36
36
sleep options [ :delay ] if options . has_key? ( :delay )
37
37
to_protocol ( args . last )
38
- end ,
38
+ end
39
39
}
40
40
41
41
redis_mock ( commands , &blk )
You can’t perform that action at this time.
0 commit comments