Skip to content

Commit 0d30623

Browse files
authored
Add support for LMPOP (#2440)
* feat: add lmpop command
1 parent 08b4cc5 commit 0d30623

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

command.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,3 +3690,65 @@ func (cmd *MapStringStringSliceCmd) readReply(rd *proto.Reader) error {
36903690
}
36913691
return nil
36923692
}
3693+
3694+
//------------------------------------------------------------------------------
3695+
3696+
type ListElementCmd struct {
3697+
baseCmd
3698+
3699+
key string
3700+
val []string
3701+
}
3702+
3703+
var _ Cmder = (*ListElementCmd)(nil)
3704+
3705+
func NewListElementCmd(ctx context.Context, args ...interface{}) *ListElementCmd {
3706+
return &ListElementCmd{
3707+
baseCmd: baseCmd{
3708+
ctx: ctx,
3709+
args: args,
3710+
},
3711+
}
3712+
}
3713+
3714+
func (cmd *ListElementCmd) SetVal(key string, val []string) {
3715+
cmd.key = key
3716+
cmd.val = val
3717+
}
3718+
3719+
func (cmd *ListElementCmd) Val() (string, []string) {
3720+
return cmd.key, cmd.val
3721+
}
3722+
3723+
func (cmd *ListElementCmd) Result() (string, []string, error) {
3724+
return cmd.key, cmd.val, cmd.err
3725+
}
3726+
3727+
func (cmd *ListElementCmd) String() string {
3728+
return cmdString(cmd, cmd.val)
3729+
}
3730+
3731+
func (cmd *ListElementCmd) readReply(rd *proto.Reader) (err error) {
3732+
if err = rd.ReadFixedArrayLen(2); err != nil {
3733+
return err
3734+
}
3735+
3736+
cmd.key, err = rd.ReadString()
3737+
if err != nil {
3738+
return err
3739+
}
3740+
3741+
n, err := rd.ReadArrayLen()
3742+
if err != nil {
3743+
return err
3744+
}
3745+
cmd.val = make([]string, n)
3746+
for i := 0; i < n; i++ {
3747+
cmd.val[i], err = rd.ReadString()
3748+
if err != nil {
3749+
return err
3750+
}
3751+
}
3752+
3753+
return nil
3754+
}

commands.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ type Cmdable interface {
225225
LInsertBefore(ctx context.Context, key string, pivot, value interface{}) *IntCmd
226226
LInsertAfter(ctx context.Context, key string, pivot, value interface{}) *IntCmd
227227
LLen(ctx context.Context, key string) *IntCmd
228+
LMPop(ctx context.Context, direction string, count int64, keys ...string) *ListElementCmd
228229
LPop(ctx context.Context, key string) *StringCmd
229230
LPopCount(ctx context.Context, key string, count int) *StringSliceCmd
230231
LPos(ctx context.Context, key string, value string, args LPosArgs) *IntCmd
@@ -1463,6 +1464,22 @@ func (c cmdable) LIndex(ctx context.Context, key string, index int64) *StringCmd
14631464
return cmd
14641465
}
14651466

1467+
// LMPop Pops one or more elements from the first non-empty list key from the list of provided key names.
1468+
// direction: left or right, count: > 0
1469+
// example: client.LMPop(ctx, "left", 3, "key1", "key2")
1470+
func (c cmdable) LMPop(ctx context.Context, direction string, count int64, keys ...string) *ListElementCmd {
1471+
args := make([]interface{}, 2+len(keys), 5+len(keys))
1472+
args[0] = "lmpop"
1473+
args[1] = len(keys)
1474+
for i, key := range keys {
1475+
args[2+i] = key
1476+
}
1477+
args = append(args, strings.ToLower(direction), "count", count)
1478+
cmd := NewListElementCmd(ctx, args...)
1479+
_ = c(ctx, cmd)
1480+
return cmd
1481+
}
1482+
14661483
func (c cmdable) LInsert(ctx context.Context, key, op string, pivot, value interface{}) *IntCmd {
14671484
cmd := NewIntCmd(ctx, "linsert", key, op, pivot, value)
14681485
_ = c(ctx, cmd)

commands_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,46 @@ var _ = Describe("Commands", func() {
22722272
Expect(lRange.Val()).To(Equal([]string{"Hello", "There", "World"}))
22732273
})
22742274

2275+
It("should LMPop", func() {
2276+
err := client.LPush(ctx, "list1", "one", "two", "three", "four", "five").Err()
2277+
Expect(err).NotTo(HaveOccurred())
2278+
2279+
err = client.LPush(ctx, "list2", "a", "b", "c", "d", "e").Err()
2280+
Expect(err).NotTo(HaveOccurred())
2281+
2282+
key, elems, err := client.LMPop(ctx, "left", 3, "list1", "list2").Result()
2283+
Expect(err).NotTo(HaveOccurred())
2284+
Expect(key).To(Equal("list1"))
2285+
Expect(elems).To(Equal([]string{"five", "four", "three"}))
2286+
2287+
key, elems, err = client.LMPop(ctx, "right", 3, "list1", "list2").Result()
2288+
Expect(err).NotTo(HaveOccurred())
2289+
Expect(key).To(Equal("list1"))
2290+
Expect(elems).To(Equal([]string{"one", "two"}))
2291+
2292+
key, elems, err = client.LMPop(ctx, "left", 1, "list1", "list2").Result()
2293+
Expect(err).NotTo(HaveOccurred())
2294+
Expect(key).To(Equal("list2"))
2295+
Expect(elems).To(Equal([]string{"e"}))
2296+
2297+
key, elems, err = client.LMPop(ctx, "right", 10, "list1", "list2").Result()
2298+
Expect(err).NotTo(HaveOccurred())
2299+
Expect(key).To(Equal("list2"))
2300+
Expect(elems).To(Equal([]string{"a", "b", "c", "d"}))
2301+
2302+
err = client.LMPop(ctx, "left", 10, "list1", "list2").Err()
2303+
Expect(err).To(Equal(redis.Nil))
2304+
2305+
err = client.Set(ctx, "list3", 1024, 0).Err()
2306+
Expect(err).NotTo(HaveOccurred())
2307+
2308+
err = client.LMPop(ctx, "left", 10, "list1", "list2", "list3").Err()
2309+
Expect(err.Error()).To(Equal("WRONGTYPE Operation against a key holding the wrong kind of value"))
2310+
2311+
err = client.LMPop(ctx, "right", 0, "list1", "list2").Err()
2312+
Expect(err).To(HaveOccurred())
2313+
})
2314+
22752315
It("should LLen", func() {
22762316
lPush := client.LPush(ctx, "list", "World")
22772317
Expect(lPush.Err()).NotTo(HaveOccurred())

0 commit comments

Comments
 (0)