func (e *RedisEngine) presence(chID ChannelID) (map[ConnID]ClientInfo, error) { conn := e.pool.Get() defer conn.Close() now := time.Now().Unix() hashKey := e.getHashKey(chID) setKey := e.getSetKey(chID) reply, err := conn.Do("ZRANGEBYSCORE", setKey, 0, now) if err != nil { return nil, err } expiredKeys, err := redis.Strings(reply, nil) if err != nil { return nil, err } if len(expiredKeys) > 0 { conn.Send("MULTI") conn.Send("ZREMRANGEBYSCORE", setKey, 0, now) for _, key := range expiredKeys { conn.Send("HDEL", hashKey, key) } _, err = conn.Do("EXEC") if err != nil { return nil, err } } reply, err = conn.Do("HGETALL", hashKey) if err != nil { return nil, err } return mapStringClientInfo(reply, nil) }
// 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), }, { "values([v1, v2])", ve(redis.Values([]interface{}{[]byte("v1"), []byte("v2")}, nil)), ve([]interface{}{[]byte("v1"), []byte("v2")}, nil), }, { "values(nil)", ve(redis.Values(nil, nil)),