Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add LMPOP #1195

Merged
merged 1 commit into from
May 30, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions lib/redis/commands/lists.rb
Original file line number Diff line number Diff line change
@@ -183,6 +183,32 @@ def brpoplpush(source, destination, timeout: 0)
send_blocking_command(command, timeout)
end

# Pops one or more elements from the first non-empty list key from the list
# of provided key names.
#
# @example Popping a element
# redis.lmpop('list')
# #=> ['list', ['a']]
# @example With count option
# redis.lmpop('list', count: 2)
# #=> ['list', ['a', 'b']]
#
# @params key [String, Array<String>] one or more keys with lists
# @params modifier [String]
# - when `"LEFT"` - the elements popped are those from the left of the list
# - when `"RIGHT"` - the elements popped are those from the right of the list
# @params count [Integer] a number of elements to pop
#
# @return [Array<String, Array<String, Float>>] list of popped elements or nil
def lmpop(*keys, modifier: "LEFT", count: nil)
raise ArgumentError, "Pick either LEFT or RIGHT" unless modifier == "LEFT" || modifier == "RIGHT"

args = [:lmpop, keys.size, *keys, modifier]
args << "COUNT" << Integer(count) if count

send_command(args)
end

# Get an element from a list by its index.
#
# @param [String] key
7 changes: 7 additions & 0 deletions lib/redis/distributed.rb
Original file line number Diff line number Diff line change
@@ -542,6 +542,13 @@ def ltrim(key, start, stop)
node_for(key).ltrim(key, start, stop)
end

# Iterate over keys, removing elements from the first non list set found.
def lmpop(*keys, modifier: "LEFT", count: nil)
ensure_same_node(:lmpop, keys) do |node|
node.lmpop(*keys, modifier: modifier, count: count)
end
end

# Get the number of members in a set.
def scard(key)
node_for(key).scard(key)
13 changes: 13 additions & 0 deletions test/lint/lists.rb
Original file line number Diff line number Diff line change
@@ -202,5 +202,18 @@ def test_variadic_rpoplpush_expand
redis.rpush('{1}bar', %w[d e f])
assert_equal 'c', redis.rpoplpush('{1}foo', '{1}bar')
end

def test_lmpop
target_version('7.0') do
assert_nil r.lmpop('{1}foo')

r.lpush('{1}foo', %w[a b c d e f g])
assert_equal ['{1}foo', ['g']], r.lmpop('{1}foo')
assert_equal ['{1}foo', ['f', 'e']], r.lmpop('{1}foo', count: 2)

r.lpush('{1}foo2', %w[a b])
assert_equal ['{1}foo', ['a']], r.lmpop('{1}foo', '{1}foo2', modifier: "RIGHT")
end
end
end
end