// zpop pops a value from the ZSET key using WATCH/MULTI/EXEC commands. func zpop(c redis.Conn, key string) (result string, err error) { defer func() { // Return connection to normal state on error. if err != nil { c.Do("DISCARD") } }() // Loop until transaction is successful. for { if _, err := c.Do("WATCH", key); err != nil { return "", err } members, err := redis.Strings(c.Do("ZRANGE", key, 0, 0)) if err != nil { return "", err } if len(members) != 1 { return "", redis.ErrNil } c.Send("MULTI") c.Send("ZREM", key, members[0]) queued, err := c.Do("EXEC") if err != nil { return "", err } if queued != nil { result = members[0] break } } return result, nil }
actual valueError expected valueError }{ { "ints([v1, v2])", ve(redis.Ints([]interface{}{[]byte("4"), []byte("5")}, nil)), ve([]int{4, 5}, nil), }, { "ints(nil)", ve(redis.Ints(nil, nil)), ve([]int(nil), redis.ErrNil), }, { "strings([v1, v2])", ve(redis.Strings([]interface{}{[]byte("v1"), []byte("v2")}, nil)), ve([]string{"v1", "v2"}, nil), }, { "strings(nil)", ve(redis.Strings(nil, nil)), ve([]string(nil), redis.ErrNil), }, { "byteslices([v1, v2])", ve(redis.ByteSlices([]interface{}{[]byte("v1"), []byte("v2")}, nil)), ve([][]byte{[]byte("v1"), []byte("v2")}, nil), }, { "byteslices(nil)", ve(redis.ByteSlices(nil, nil)),