Skip to content

Commit ff4399b

Browse files
✨ Add BLMPOP (#1199)
* ✨ Add BLMPOP * 🚨 Fix rubocop error
1 parent fde7873 commit ff4399b

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

lib/redis/commands/lists.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,34 @@ def brpoplpush(source, destination, timeout: 0)
183183
send_blocking_command(command, timeout)
184184
end
185185

186+
# Pops one or more elements from the first non-empty list key from the list
187+
# of provided key names. If lists are empty, blocks until timeout has passed.
188+
#
189+
# @example Popping a element
190+
# redis.blmpop(1.0, 'list')
191+
# #=> ['list', ['a']]
192+
# @example With count option
193+
# redis.blmpop(1.0, 'list', count: 2)
194+
# #=> ['list', ['a', 'b']]
195+
#
196+
# @params timeout [Float] a float value specifying the maximum number of seconds to block) elapses.
197+
# A timeout of zero can be used to block indefinitely.
198+
# @params key [String, Array<String>] one or more keys with lists
199+
# @params modifier [String]
200+
# - when `"LEFT"` - the elements popped are those from the left of the list
201+
# - when `"RIGHT"` - the elements popped are those from the right of the list
202+
# @params count [Integer] a number of elements to pop
203+
#
204+
# @return [Array<String, Array<String, Float>>] list of popped elements or nil
205+
def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
206+
raise ArgumentError, "Pick either LEFT or RIGHT" unless modifier == "LEFT" || modifier == "RIGHT"
207+
208+
args = [:lmpop, keys.size, *keys, modifier]
209+
args << "COUNT" << Integer(count) if count
210+
211+
send_blocking_command(args, timeout)
212+
end
213+
186214
# Pops one or more elements from the first non-empty list key from the list
187215
# of provided key names.
188216
#

lib/redis/distributed.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,14 @@ def ltrim(key, start, stop)
542542
node_for(key).ltrim(key, start, stop)
543543
end
544544

545-
# Iterate over keys, removing elements from the first non list set found.
545+
# Iterate over keys, blocking and removing elements from the first non empty liist found.
546+
def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
547+
ensure_same_node(:blmpop, keys) do |node|
548+
node.blmpop(timeout, *keys, modifier: modifier, count: count)
549+
end
550+
end
551+
552+
# Iterate over keys, removing elements from the first non list found.
546553
def lmpop(*keys, modifier: "LEFT", count: nil)
547554
ensure_same_node(:lmpop, keys) do |node|
548555
node.lmpop(*keys, modifier: modifier, count: count)

test/lint/lists.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,19 @@ def test_variadic_rpoplpush_expand
203203
assert_equal 'c', redis.rpoplpush('{1}foo', '{1}bar')
204204
end
205205

206+
def test_blmpop
207+
target_version('7.0') do
208+
assert_nil r.blmpop(1.0, '{1}foo')
209+
210+
r.lpush('{1}foo', %w[a b c d e f g])
211+
assert_equal ['{1}foo', ['g']], r.blmpop(1.0, '{1}foo')
212+
assert_equal ['{1}foo', ['f', 'e']], r.blmpop(1.0, '{1}foo', count: 2)
213+
214+
r.lpush('{1}foo2', %w[a b])
215+
assert_equal ['{1}foo', ['a']], r.blmpop(1.0, '{1}foo', '{1}foo2', modifier: "RIGHT")
216+
end
217+
end
218+
206219
def test_lmpop
207220
target_version('7.0') do
208221
assert_nil r.lmpop('{1}foo')

0 commit comments

Comments
 (0)