Skip to content

Commit 9d49a83

Browse files
authored
Merge pull request #1129 from casperisfine/double-timeouts
Remove positional timeout and better accept Float values
2 parents 48b2789 + d93bca3 commit 9d49a83

File tree

5 files changed

+39
-92
lines changed

5 files changed

+39
-92
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
- Use `MD5` for hashing server nodes in `Redis::Distributed`. This should improve keys distribution among servers. See #1089.
66
- Cluster support has been moved to a `redis_cluster` companion gem.
77
- `select` no longer record the current database. If the client has to reconnect after `select` was used, it will reconnect to the original database.
8+
- Better support Float timeout in blocking commands. See #977.
9+
- Removed positional timeout in blocking commands (`BLPOP`, etc). Timeout now must be passed as an option: `r.blpop("key", timeout: 2.5)`
810
- Removed `logger` option.
911
- Removed `reconnect_delay_max` and `reconnect_delay`, you can pass precise sleep durations to `reconnect_attempts` instead.
1012
- Require Ruby 2.5+.

lib/redis/commands/lists.rb

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def lmove(source, destination, where_source, where_destination)
4848
# @param [String, Symbol] where_destination where to push the element to the source list
4949
# e.g. 'LEFT' - to head, 'RIGHT' - to tail
5050
# @param [Hash] options
51-
# - `:timeout => Numeric`: timeout in seconds, defaults to no timeout
51+
# - `:timeout => [Float, Integer]`: timeout in seconds, defaults to no timeout
5252
#
5353
# @return [nil, String] the element, or nil when the source key does not exist or the timeout expired
5454
#
@@ -142,7 +142,7 @@ def rpoplpush(source, destination)
142142
# @param [String, Array<String>] keys one or more keys to perform the
143143
# blocking pop on
144144
# @param [Hash] options
145-
# - `:timeout => Integer`: timeout in seconds, defaults to no timeout
145+
# - `:timeout => [Float, Integer]`: timeout in seconds, defaults to no timeout
146146
#
147147
# @return [nil, [String, String]]
148148
# - `nil` when the operation timed out
@@ -156,7 +156,7 @@ def blpop(*args)
156156
# @param [String, Array<String>] keys one or more keys to perform the
157157
# blocking pop on
158158
# @param [Hash] options
159-
# - `:timeout => Integer`: timeout in seconds, defaults to no timeout
159+
# - `:timeout => [Float, Integer]`: timeout in seconds, defaults to no timeout
160160
#
161161
# @return [nil, [String, String]]
162162
# - `nil` when the operation timed out
@@ -173,12 +173,12 @@ def brpop(*args)
173173
# @param [String] source source key
174174
# @param [String] destination destination key
175175
# @param [Hash] options
176-
# - `:timeout => Integer`: timeout in seconds, defaults to no timeout
176+
# - `:timeout => [Float, Integer]`: timeout in seconds, defaults to no timeout
177177
#
178178
# @return [nil, String]
179179
# - `nil` when the operation timed out
180180
# - the element was popped and pushed otherwise
181-
def brpoplpush(source, destination, deprecated_timeout = 0, timeout: deprecated_timeout)
181+
def brpoplpush(source, destination, timeout: 0)
182182
command = [:brpoplpush, source, destination, timeout]
183183
send_blocking_command(command, timeout)
184184
end
@@ -253,20 +253,16 @@ def _bpop(cmd, args, &blk)
253253
timeout = if args.last.is_a?(Hash)
254254
options = args.pop
255255
options[:timeout]
256-
elsif args.last.respond_to?(:to_int)
257-
# Issue deprecation notice in obnoxious mode...
258-
args.pop.to_int
259256
end
260257

261258
timeout ||= 0
262-
263-
if args.size > 1
264-
# Issue deprecation notice in obnoxious mode...
259+
unless timeout.is_a?(Integer) || timeout.is_a?(Float)
260+
raise ArgumentError, "timeout must be an Integer or Float, got: #{timeout.class}"
265261
end
266262

267-
keys = args.flatten
268-
269-
command = [cmd, keys, timeout]
263+
command = [cmd]
264+
command.concat(args.flatten)
265+
command << timeout
270266
send_blocking_command(command, timeout, &blk)
271267
end
272268

lib/redis/distributed.rb

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -460,13 +460,6 @@ def _bpop(cmd, args)
460460
timeout = if args.last.is_a?(Hash)
461461
options = args.pop
462462
options[:timeout]
463-
elsif args.last.respond_to?(:to_int)
464-
# Issue deprecation notice in obnoxious mode...
465-
args.pop.to_int
466-
end
467-
468-
if args.size > 1
469-
# Issue deprecation notice in obnoxious mode...
470463
end
471464

472465
keys = args.flatten
@@ -486,6 +479,18 @@ def blpop(*args)
486479
_bpop(:blpop, args)
487480
end
488481

482+
def bzpopmax(*args)
483+
_bpop(:bzpopmax, args) do |reply|
484+
reply.is_a?(Array) ? [reply[0], reply[1], Floatify.call(reply[2])] : reply
485+
end
486+
end
487+
488+
def bzpopmin(*args)
489+
_bpop(:bzpopmin, args) do |reply|
490+
reply.is_a?(Array) ? [reply[0], reply[1], Floatify.call(reply[2])] : reply
491+
end
492+
end
493+
489494
# Remove and get the last element in a list, or block until one is
490495
# available.
491496
def brpop(*args)
@@ -494,9 +499,9 @@ def brpop(*args)
494499

495500
# Pop a value from a list, push it to another list and return it; or block
496501
# until one is available.
497-
def brpoplpush(source, destination, deprecated_timeout = 0, **options)
502+
def brpoplpush(source, destination, **options)
498503
ensure_same_node(:brpoplpush, [source, destination]) do |node|
499-
node.brpoplpush(source, destination, deprecated_timeout, **options)
504+
node.brpoplpush(source, destination, **options)
500505
end
501506
end
502507

test/distributed/blocking_commands_test.rb

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,15 @@ def test_blpop_raises
2020
end
2121
end
2222

23-
def test_blpop_raises_with_old_prototype
24-
assert_raises(Redis::Distributed::CannotDistribute) do
25-
r.blpop('foo', 'bar', 0)
26-
end
27-
end
28-
2923
def test_brpop_raises
3024
assert_raises(Redis::Distributed::CannotDistribute) do
3125
r.brpop(%w[foo bar])
3226
end
3327
end
3428

35-
def test_brpop_raises_with_old_prototype
36-
assert_raises(Redis::Distributed::CannotDistribute) do
37-
r.brpop('foo', 'bar', 0)
38-
end
39-
end
40-
4129
def test_brpoplpush_raises
4230
assert_raises(Redis::Distributed::CannotDistribute) do
4331
r.brpoplpush('foo', 'bar')
4432
end
4533
end
46-
47-
def test_brpoplpush_raises_with_old_prototype
48-
assert_raises(Redis::Distributed::CannotDistribute) do
49-
r.brpoplpush('foo', 'bar', 0)
50-
end
51-
end
52-
53-
def test_bzpopmin
54-
# Not implemented yet
55-
end
56-
57-
def test_bzpopmax
58-
# Not implemented yet
59-
end
6034
end

test/lint/blocking_commands.rb

Lines changed: 13 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -101,22 +101,8 @@ def to_int
101101
end
102102

103103
def test_blpop_integer_like_timeout
104-
mock do |r|
105-
assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", FakeDuration.new(1))
106-
end
107-
end
108-
109-
def test_blpop_with_old_prototype
110-
assert_equal ['{zap}foo', 's1'], r.blpop('{zap}foo', 0)
111-
assert_equal ['{zap}foo', 's2'], r.blpop('{zap}foo', 0)
112-
assert_equal ['{zap}bar', 's1'], r.blpop('{zap}bar', '{zap}foo', 0)
113-
assert_equal ['{zap}bar', 's2'], r.blpop('{zap}foo', '{zap}bar', 0)
114-
end
115-
116-
def test_blpop_timeout_with_old_prototype
117-
mock do |r|
118-
assert_equal ['{zap}foo', '0'], r.blpop('{zap}foo', 0)
119-
assert_equal ['{zap}foo', '1'], r.blpop('{zap}foo', 1)
104+
assert_raises ArgumentError do
105+
assert_equal ["{zap}foo", "1"], r.blpop("{zap}foo", timeout: FakeDuration.new(1))
120106
end
121107
end
122108

@@ -134,20 +120,6 @@ def test_brpop_timeout
134120
end
135121
end
136122

137-
def test_brpop_with_old_prototype
138-
assert_equal ['{zap}foo', 's2'], r.brpop('{zap}foo', 0)
139-
assert_equal ['{zap}foo', 's1'], r.brpop('{zap}foo', 0)
140-
assert_equal ['{zap}bar', 's2'], r.brpop('{zap}bar', '{zap}foo', 0)
141-
assert_equal ['{zap}bar', 's1'], r.brpop('{zap}foo', '{zap}bar', 0)
142-
end
143-
144-
def test_brpop_timeout_with_old_prototype
145-
mock do |r|
146-
assert_equal ['{zap}foo', '0'], r.brpop('{zap}foo', 0)
147-
assert_equal ['{zap}foo', '1'], r.brpop('{zap}foo', 1)
148-
end
149-
end
150-
151123
def test_brpoplpush
152124
assert_equal 's2', r.brpoplpush('{zap}foo', '{zap}qux')
153125
assert_equal ['s2'], r.lrange('{zap}qux', 0, -1)
@@ -160,26 +132,24 @@ def test_brpoplpush_timeout
160132
end
161133
end
162134

163-
def test_brpoplpush_with_old_prototype
164-
assert_equal 's2', r.brpoplpush('{zap}foo', '{zap}qux', 0)
165-
assert_equal ['s2'], r.lrange('{zap}qux', 0, -1)
135+
def test_bzpopmin
136+
assert_equal ['{szap}foo', 'a', 0.0], r.bzpopmin('{szap}foo', '{szap}bar', timeout: 1)
166137
end
167138

168-
def test_brpoplpush_timeout_with_old_prototype
169-
mock do |r|
170-
assert_equal '0', r.brpoplpush('{zap}foo', '{zap}bar', 0)
171-
assert_equal '1', r.brpoplpush('{zap}foo', '{zap}bar', 1)
139+
def test_bzpopmin_float_timeout
140+
target_version "6.0" do
141+
assert_nil r.bzpopmin('{szap}aaa', '{szap}bbb', timeout: LOW_TIMEOUT)
172142
end
173143
end
174144

175-
def test_bzpopmin
176-
assert_equal ['{szap}foo', 'a', 0.0], r.bzpopmin('{szap}foo', '{szap}bar', 1)
177-
assert_nil r.bzpopmin('{szap}aaa', '{szap}bbb', 2)
145+
def test_bzpopmax
146+
assert_equal ['{szap}foo', 'c', 2.0], r.bzpopmax('{szap}foo', '{szap}bar', timeout: 1)
178147
end
179148

180-
def test_bzpopmax
181-
assert_equal ['{szap}foo', 'c', 2.0], r.bzpopmax('{szap}foo', '{szap}bar', 1)
182-
assert_nil r.bzpopmax('{szap}aaa', '{szap}bbb', 1)
149+
def test_bzpopmax_float_timeout
150+
target_version "6.0" do
151+
assert_nil r.bzpopmax('{szap}aaa', '{szap}bbb', timeout: LOW_TIMEOUT)
152+
end
183153
end
184154

185155
def test_blmove_socket_timeout

0 commit comments

Comments
 (0)