func TestHashMget(t *testing.T) { s, err := Run() ok(t, err) defer s.Close() c, err := redis.Dial("tcp", s.Addr()) ok(t, err) s.HSet("wim", "zus", "jet") s.HSet("wim", "teun", "vuur") s.HSet("wim", "gijs", "lam") s.HSet("wim", "kees", "bok") v, err := redis.Values(c.Do("HMGET", "wim", "zus", "nosuch", "kees")) ok(t, err) equals(t, 3, len(v)) equals(t, "jet", string(v[0].([]byte))) equals(t, nil, v[1]) equals(t, "bok", string(v[2].([]byte))) v, err = redis.Values(c.Do("HMGET", "nosuch", "zus", "kees")) ok(t, err) equals(t, 2, len(v)) equals(t, nil, v[0]) equals(t, nil, v[1]) // Wrong key type s.Set("foo", "bar") _, err = redis.Int(c.Do("HMGET", "foo", "bar")) assert(t, err != nil, "no HMGET error") }
func (c *client) QPeek(queueName string, count int) ([]job, error) { conn, err := c.get() if err != nil { return nil, err } reply, err := redis.Values(conn.Do("QPEEK", queueName, count)) if err != nil { return nil, err } result := make([]job, 0, len(reply)) for _, v := range reply { if value, err := redis.Values(v, nil); err != nil { return nil, err } else { queueName, err := redis.String(value[0], nil) id, err := redis.String(value[1], err) data, err := redis.Bytes(value[2], err) if err != nil { return nil, err } result = append(result, job{QueueName: queueName, Id: id, Body: data}) } } return result, nil }
func (mapDec *mapDecoder) decode(node RMNode, data interface{}, v reflect.Value) { values, err := redis.Values(node.Value(), nil) if err != nil { panic(err) } size := len(values) / 2 vals, err := redis.Values(node.Value(), nil) if err != nil { panic(err) } v.Set(reflect.MakeMap(v.Type())) for i := 0; i < size; i++ { mKey, err := redis.String(values[i*2], nil) if err != nil { panic(err) } elemV := newValueForType(v.Type().Elem()) if i < node.Size() { mapDec.elemFunc(node.Child(i), vals[i*2+1], elemV) } else { mapDec.elemFunc(node, vals[i*2+1], elemV) } v.SetMapIndex(reflect.ValueOf(mKey), elemV) } }
func SlotsInfo(addr, passwd string, fromSlot, toSlot int) (map[int]int, error) { c, err := DialTo(addr, passwd) if err != nil { return nil, err } defer c.Close() infos, err := redis.Values(c.Do("SLOTSINFO", fromSlot, toSlot-fromSlot+1)) if err != nil { return nil, errors.Trace(err) } slots := make(map[int]int) if infos != nil { for i := 0; i < len(infos); i++ { info, err := redis.Values(infos[i], nil) if err != nil { return nil, errors.Trace(err) } var slotid, slotsize int if _, err := redis.Scan(info, &slotid, &slotsize); err != nil { return nil, errors.Trace(err) } else { slots[slotid] = slotsize } } } return slots, nil }
func TestMget(t *testing.T) { s, err := Run() ok(t, err) defer s.Close() c, err := redis.Dial("tcp", s.Addr()) ok(t, err) s.Set("zus", "jet") s.Set("teun", "vuur") s.Set("gijs", "lam") s.Set("kees", "bok") { v, err := redis.Values(c.Do("MGET", "zus", "nosuch", "kees")) ok(t, err) equals(t, 3, len(v)) equals(t, "jet", string(v[0].([]byte))) equals(t, nil, v[1]) equals(t, "bok", string(v[2].([]byte))) } // Wrong key type returns nil { s.HSet("aap", "foo", "bar") v, err := redis.Values(c.Do("MGET", "aap")) ok(t, err) equals(t, 1, len(v)) equals(t, nil, v[0]) } }
// offset From where to scan. // prefix The prefix string to scan. // // Return: (offset, keys, error), if the offset is 0, means the scan is over. func ListKeys(offset int64, prefix *string) (int64, []string, error) { if prefix == nil { return 0, nil, errors.New("Prefix can't be nil.") } conn, err := getConn() if err != nil { return 0, nil, err } defer (*conn).Close() var v []interface{} v, err = redis.Values((*conn).Do("SCAN", offset, *prefix)) if err != nil { return 0, nil, err } var newOffset int64 newOffsetS := string(v[0].([]byte)) newOffset, err = strconv.ParseInt(newOffsetS, 10, 64) if err != nil { return 0, nil, err } keys := make([]string, 0) sv, _ := redis.Values(v[1], nil) for _, value := range sv { key := string(value.([]byte)) keys = append(keys, key) } return newOffset, keys, nil }
func (r *RedisCache) ZRangeByScore(v interface{}, set string, dir bool, limit int64) ([]int64, error) { var values []interface{} var err error t := GetBaseType(v) // Using LIMIT offset for pagination has bad performance // so always use 0 offset and implement elsewhere if dir == HIGH_TO_LOW { values, err = redis.Values(r.C.Do( "ZREVRANGEBYSCORE", "set"+r.Sep+r.GetTypePrefix(t)+r.Sep+set, "+inf", "-inf", "WITHSCORES", "LIMIT", "0", strconv.FormatInt(limit, 10))) } else { // LOW_TO_HIGH values, err = redis.Values(r.C.Do( "ZRANGEBYSCORE", "set"+r.Sep+r.GetTypePrefix(t)+r.Sep+set, "-inf", "+inf", "WITHSCORES", "LIMIT", "0", strconv.FormatInt(limit, 10))) } if err != nil { return nil, err } val := reflect.ValueOf(v) switch val.Kind() { case reflect.Ptr: val = reflect.Indirect(val) } reply_len := len(values) / 2 list := reflect.MakeSlice(val.Type(), reply_len, reply_len) scores := make([]int64, reply_len) for i := 0; i < reply_len; i++ { scores[i], err = redis.Int64(values[(i*2)+1], nil) if err != nil { return nil, err } b, err := redis.Bytes(values[i*2], nil) if err != nil { return nil, err } r.S.Unmarshal(b, list.Index(i).Addr().Interface()) } val.Set(list) return scores, nil }
func SendOfflineMsg(client *Client, appid string) { // connect to Redis redisConn, err := redis.Dial("tcp", ":6379") if err != nil { log.Printf("Dial redix error: %s", err.Error()) return } // get the timestamp var reply []interface{} reply, err = redis.Values(redisConn.Do("TIME")) if err != nil { log.Printf("Error on TIME: %s", err.Error()) return } var current_time int64 _, err = redis.Scan(reply, ¤t_time) // get offline message for each App on this device key := "broadcast_msg:" + appid reply, err = redis.Values(redisConn.Do("ZRANGE", key, 0, -1)) if err != nil { log.Printf("Error on ZRANGE: %s", err.Error()) goto Out } for len(reply) > 0 { var msg_id int64 reply, err = redis.Scan(reply, &msg_id) if err != nil { log.Printf("Error on Scan ZRANGE reply: %s", err.Error()) goto Out } log.Printf("offline msg_id: %d", msg_id) key = "msg:" + strconv.FormatInt(msg_id, 10) var reply_msg []interface{} reply_msg, err = redis.Values(redisConn.Do("HMGET", key, "msg", "expire_time")) if err != nil { log.Printf("Error on HMGET: %s", err.Error()) goto Out } var msg string var expire_time int64 _, err = redis.Scan(reply_msg, &msg, &expire_time) if err != nil { log.Printf("Error on Scan HMGET reply: %s", err.Error()) goto Out } //log.Printf("expire_time: %d, msg: %s", expire_time, msg) if expire_time > current_time { // message hasn't expired, need to send it client.SendMsg(msg, appid) } } Out: redisConn.Close() }
func main() { m := martini.Classic() // Handle the "/results" API method m.Get("/results/:check_id", func(params martini.Params, res http.ResponseWriter, req *http.Request) string { conn := redisPool.Get() // Parse the url to get the query paramenter named "limit" and convert to int limit, _ := strconv.ParseInt(req.URL.Query().Get("limit"), 10, 64) // Query redis for the last "limit" results for the given "check_id" reply, err := redis.Values(conn.Do("LRANGE", "results:"+params["check_id"], -limit, -1)) for { if err == nil { break } else { log.Printf("Redis error in LRANGE results: %s\n", err) reply, err = redis.Values(conn.Do("LRANGE", "results:"+params["check_id"], -limit, -1)) } } conn.Close() return string(getJsonResults(reply)) }) // Handle the "/checks" API method m.Get("/checks", func(params martini.Params) string { conn := redisPool.Get() // Query redis all the available "checks" reply, err := redis.Values(conn.Do("LRANGE", "checks", 0, -1)) for { if err == nil { break } else { log.Printf("Redis error in LRANGE checks: %s\n", err) reply, err = redis.Values(conn.Do("LRANGE", "checks", 0, -1)) } } conn.Close() return string(getJsonChecks(reply)) }) fmt.Printf("[martini] Listening on port 5000\n") err := http.ListenAndServe("0.0.0.0:5000", m) if err != nil { fmt.Printf("Error: %s", err) } }
func LoadUserAccessToken(token string) (int64, int64, string, error) { conn := redis_pool.Get() defer conn.Close() key := fmt.Sprintf("access_token_%s", token) var uid int64 var appid int64 var uname string exists, err := redis.Bool(conn.Do("EXISTS", key)) if err != nil { return 0, 0, "", err } if !exists { return 0, 0, "", errors.New("token non exists") } reply, err := redis.Values(conn.Do("HMGET", key, "user_id", "app_id", "user_name")) if err != nil { log.Info("hmget error:", err) return 0, 0, "", err } _, err = redis.Scan(reply, &uid, &appid, &uname) if err != nil { log.Warning("scan error:", err) return 0, 0, "", err } return appid, uid, uname, nil }
func (oper *MultiOperator) mgetResults(mop *MulOp) ([]byte, error) { slotmap := getSlotMap(mop.keys) results := make([]interface{}, len(mop.keys)) conn := oper.pool.Get() defer conn.Close() for _, vec := range slotmap { req := make([]interface{}, 0, len(vec)) for _, p := range vec { req = append(req, p.key) } replys, err := redis.Values(conn.Do("mget", req...)) if err != nil { return nil, errors.Trace(err) } for i, reply := range replys { if reply != nil { results[vec[i].pos] = reply } else { results[vec[i].pos] = nil } } } b, err := respcoding.Marshal(results) return b, errors.Trace(err) }
func (r *RedisStorageManager) GetAndDeleteSet(keyName string) []interface{} { db := r.pool.Get() defer db.Close() log.Debug("Getting raw gkey set: ", keyName) if db == nil { log.Warning("Connection dropped, connecting..") r.Connect() r.GetAndDeleteSet(keyName) } else { log.Debug("keyName is: ", keyName) fixedKey := r.fixKey(keyName) log.Debug("Fixed keyname is: ", fixedKey) db.Send("MULTI") // Get all the elements db.Send("LRANGE", fixedKey, 0, -1) // Trim it to zero db.Send("DEL", fixedKey) // Execute r, err := redis.Values(db.Do("EXEC")) vals := r[0].([]interface{}) log.Debug("Returned: ", vals) if err != nil { log.Error("Multi command failed: ", err) } return vals } return []interface{}{} }
func TestBlankCommmand(t *testing.T) { c, err := redis.DialTestDB() if err != nil { t.Fatalf("error connection to database, %v", err) } defer c.Close() for _, cmd := range testCommands { if err := c.Send(cmd.args[0].(string), cmd.args[1:]...); err != nil { t.Fatalf("Send(%v) returned error %v", cmd.args, err) } } reply, err := redis.Values(c.Do("")) if err != nil { t.Fatalf("Do() returned error %v", err) } if len(reply) != len(testCommands) { t.Fatalf("len(reply)=%d, want %d", len(reply), len(testCommands)) } for i, cmd := range testCommands { actual := reply[i] if !reflect.DeepEqual(actual, cmd.expected) { t.Errorf("Receive(%v) = %v, want %v", cmd.args, actual, cmd.expected) } } }
func (iter *RedisIterator) Next() bool { iter.cursor += 1 if len(iter.cacheJob) > 0 && len(iter.cacheJob) > iter.cursor { return true } start := iter.start stop := iter.start + iter.limit - 1 iter.start = iter.start + iter.limit var err error var conn = iter.r.pool.Get() defer conn.Close() var key string if iter.Func == nil { key = REDIS_PREFIX + "ID" } else { key = REDIS_PREFIX + string(iter.Func) + ":name" } reply, err := redis.Values(conn.Do("ZRANGE", key, start, stop, "WITHSCORES")) if err != nil || len(reply) == 0 { return false } var jobId int64 jobs := make([]driver.Job, len(reply)/2) for k, v := range reply { if k%2 == 1 { jobId, _ = strconv.ParseInt(string(v.([]byte)), 10, 0) jobs[(k-1)/2], _ = iter.r.get(jobId) } } iter.cacheJob = jobs iter.cursor = 0 return true }
func (self *SortedSetGenerator) checkZrange(conn redis.Conn, req_num int32, range_data int32, mytime *time.Timer) { var pos int32 = 0 for ; pos < req_num; pos++ { select { case <-mytime.C: return default: value := self.data_list[pos%ZRANGE_ALL] reporter.Resultdata.AddSendQuantity() reply, err := redis.Values(conn.Do("ZRANGE", value.key, 0, range_data)) //log.Info("redis operating: zrange %d 0 %d", value.key, range_data) if err != nil { log.Info("redis operating: zrange %d 0 %d error %v", value.key, range_data, err) reporter.Resultdata.AddFailQuantity() } else { //log.Info(" zrange %d 0 %d ret:%v", value.key, range_data, reply) /*type IntArrayChecker struct { myuid []int64 youruid []interface{} }*/ datacheck := &reporter.IntArrayChecker{Myuid: value.sortedlist, Youruid: reply} reporter.Datasummer.AddChecker(datacheck) } } } }
// checkRole check the current redis role. func checkRole(addr string, role string) bool { if addr == "" { return false } // Step 3: call the ROLE command in the target instance conn, err := redis.DialTimeout("tcp", addr, sentinelTimeout, sentinelTimeout, sentinelTimeout) if err != nil { log.Error("redis.DialTimeout(\"tcp\", \"%s\", 500ms...) error(%v)", addr, err) return false } defer conn.Close() replies, err := redis.Values(conn.Do("ROLE")) if err != nil { log.Error("conn.Do(\"ROLE\") error(%v)", err) return false } if len(replies) < 1 { return false } curRole, err := redis.String(replies[0], nil) if err != nil { log.Error("redis.String(replies[0], nil) error(%v)", err) return false } log.Info("redis: \"%s\" role: \"%s\"", addr, curRole) if curRole == role { return true } return false }
// get redis's slot size func SlotsInfo(addr string, fromSlot, toSlot int) (map[int]int, error) { c, err := redis.DialTimeout("tcp", addr, defaultTimeout, defaultTimeout, defaultTimeout) if err != nil { return nil, err } defer c.Close() var reply []interface{} var val []interface{} reply, err = redis.Values(c.Do("SLOTSINFO", fromSlot, toSlot-fromSlot+1)) if err != nil { return nil, err } ret := make(map[int]int) for { if reply == nil || len(reply) == 0 { break } if reply, err = redis.Scan(reply, &val); err != nil { return nil, err } var slot, keyCount int _, err := redis.Scan(val, &slot, &keyCount) if err != nil { return nil, err } ret[slot] = keyCount } return ret, nil }
func ExampleScanSlice() { c, err := dial() if err != nil { fmt.Println(err) return } defer c.Close() c.Send("HMSET", "album:1", "title", "Red", "rating", 5) c.Send("HMSET", "album:2", "title", "Earthbound", "rating", 1) c.Send("HMSET", "album:3", "title", "Beat", "rating", 4) c.Send("LPUSH", "albums", "1") c.Send("LPUSH", "albums", "2") c.Send("LPUSH", "albums", "3") values, err := redis.Values(c.Do("SORT", "albums", "BY", "album:*->rating", "GET", "album:*->title", "GET", "album:*->rating")) if err != nil { fmt.Println(err) return } var albums []struct { Title string Rating int } if err := redis.ScanSlice(values, &albums); err != nil { fmt.Println(err) return } fmt.Printf("%v\n", albums) // Output: // [{Earthbound 1} {Beat 4} {Red 5}] }
func (logger *RedisLogger) zcards(key string, days int) []int64 { if days <= 0 { days = 1 } t := time.Now() d, _ := time.ParseDuration("-24h") conn := logger.conn conn.Send("MULTI") conn.Send("ZCARD", key+DateString(t)) for i := 1; i < days; i++ { t = t.Add(d) conn.Send("ZCARD", key+DateString(t)) } values, err := redis.Values(conn.Do("EXEC")) if err != nil { log.Println(err) return nil } counts := make([]int64, len(values)) for i, v := range values { counts[i], _ = v.(int64) } return counts }
func (logger *RedisLogger) FriendCount(userid string) (follows, followers, friends, blacklist int) { conn := logger.conn conn.Send("MULTI") conn.Send("SCARD", redisUserFollowPrefix+userid) conn.Send("SCARD", redisUserFollowerPrefix+userid) conn.Send("SCARD", redisUserBlacklistPrefix+userid) values, err := redis.Values(conn.Do("EXEC")) if err != nil { log.Println(err) return } counts := make([]int, 3) if err := redis.ScanSlice(values, &counts); err != nil { log.Println(err) return } follows = counts[0] followers = counts[1] blacklist = counts[2] friends = len(logger.Friends("friend", userid)) return }
func (self *HashGenerator) hmget(conn redis.Conn, reqnum int32, mytime *time.Timer) { length := int32(len(self.data_list)) var i int32 = 0 for ; i < reqnum; i++ { select { case <-mytime.C: return default: values := self.data_list[i%length] key := values.key lengh := len(values.names) name_slice := make([]interface{}, lengh) value_slice := make([]int64, lengh) for pos, data := range values.names { name_slice[pos] = data.name value_slice[pos] = data.value } reporter.Resultdata.AddSendQuantity() reply, err := redis.Values(conn.Do("hmget", key, name_slice)) if err != nil { log.Error("redis hmget failed: [%s:%v],err %v", key, name_slice, err) reporter.Resultdata.AddFailQuantity() } else { //reporter.Resultdata.AddSuccQuantity() datacheck := &reporter.IntArrayChecker{value_slice, reply} reporter.Datasummer.AddChecker(datacheck) } } } }
func getProcedure(pool *redis.Pool, endpoint URI) *registrationInfo { conn := pool.Get() defer conn.Close() proceduresKey := fmt.Sprintf("procedures:%s", endpoint) procedures, err := redis.Strings(conn.Do("ZREVRANGE", proceduresKey, 0, 1)) if err != nil { out.Debug("Redis error on key %s: %v", proceduresKey, err) return nil } if len(procedures) == 0 { return nil } info := registrationInfo{} reply, err := redis.Values(conn.Do("HGETALL", procedures[0])) if err != nil { out.Debug("Redis error on key %s: %v", procedures[0], err) return nil } err = redis.ScanStruct(reply, &info) if err != nil { out.Debug("Redis error on key %s: %v", procedures[0], err) return nil } return &info }
func (self *SortedSetGenerator) checkZrevrange(conn redis.Conn, req_num int32, mytime *time.Timer) { var pos int32 = 0 for _, value := range self.data_list { select { case <-mytime.C: return default: if pos >= req_num { break } reporter.Resultdata.AddSendQuantity() reply, err := redis.Values(conn.Do("zrevrange", value.key, 0, ZRANGE_100)) //log.Info("redis operating: zrevrange %d 0 %d", value.key, ZRANGE_100) if err != nil { log.Info("redis operating: zrevrange %d 0 %d error %v", value.key, ZRANGE_100, err) reporter.Resultdata.AddFailQuantity() } else { if len(reply) > 0 { reporter.Resultdata.AddSuccQuantity() } else { reporter.Resultdata.AddErrorQuantity() } } pos++ } } }
func (db *Database) getDoc(c redis.Conn, path string) (*doc.Package, time.Time, error) { r, err := redis.Values(getDocScript.Do(c, path)) if err == redis.ErrNil { return nil, time.Time{}, nil } else if err != nil { return nil, time.Time{}, err } var p []byte var t int64 if _, err := redis.Scan(r, &p, &t); err != nil { return nil, time.Time{}, err } p, err = snappy.Decode(nil, p) if err != nil { return nil, time.Time{}, err } var pdoc doc.Package if err := gob.NewDecoder(bytes.NewReader(p)).Decode(&pdoc); err != nil { return nil, time.Time{}, err } nextCrawl := pdoc.Updated if t != 0 { nextCrawl = time.Unix(t, 0).UTC() } return &pdoc, nextCrawl, err }
// get redis's slot size func SlotsInfo(addr string, fromSlot int, toSlot int, auth string) (map[int]int, error) { c, err := newRedisConn(addr, auth) if err != nil { return nil, errors.Trace(err) } defer c.Close() var ( reply []interface{} val []interface{} ) reply, err = redis.Values(c.Do("SLOTSINFO", fromSlot, toSlot-fromSlot+1)) if err != nil { return nil, errors.Trace(err) } ret := map[int]int{} for { if reply == nil || len(reply) == 0 { break } if reply, err = redis.Scan(reply, &val); err != nil { return nil, errors.Trace(err) } var slot, keyCount int _, err := redis.Scan(val, &slot, &keyCount) if err != nil { return nil, errors.Trace(err) } ret[slot] = keyCount } return ret, nil }
func (s *QueueSubscriber) redisPop(ch chan response) { var res response reply, err := redis.Values(s.conn.Do(QueueSubCmd, s.queue, 0)) if err != nil { res.err = err ch <- res return } var qName string var msg string if _, err := redis.Scan(reply, &qName, &msg); err != nil { res.err = err ch <- res return } // base64 decode msg b, err := base64.StdEncoding.DecodeString(msg) if err != nil { res.err = err ch <- res return } res.b = b ch <- res }
func TestSendReceiveWithWait(t *testing.T) { conn := NewConn() conn.ReceiveWait = true conn.Command("HGETALL", "person:1").ExpectMap(map[string]string{ "name": "Mr. Johson", "age": "42", }) conn.Command("HGETALL", "person:2").ExpectMap(map[string]string{ "name": "Ms. Jennifer", "age": "28", }) ids := []string{"1", "2"} for _, id := range ids { conn.Send("HGETALL", fmt.Sprintf("person:%s", id)) } var people []Person var peopleLock sync.RWMutex go func() { for i := 0; i < len(ids); i++ { values, err := redis.Values(conn.Receive()) if err != nil { t.Fatal(err) } var person Person err = redis.ScanStruct(values, &person) if err != nil { t.Fatal(err) } peopleLock.Lock() people = append(people, person) peopleLock.Unlock() } }() for i := 0; i < len(ids); i++ { conn.ReceiveNow <- true } time.Sleep(10 * time.Millisecond) peopleLock.RLock() defer peopleLock.RUnlock() if len(people) != 2 { t.Fatalf("Wrong number of people. Expected '2' and got '%d'", len(people)) } if people[0].Name != "Mr. Johson" || people[1].Name != "Ms. Jennifer" { t.Error("People name order are wrong") } if people[0].Age != 42 || people[1].Age != 28 { t.Error("People age order are wrong") } }
///region CategoryRedis func AddCategoryRedis(name string) error { conn, err := redis.Dial("tcp", "localhost:6379") if err != nil { return err } conn.Do("AUTH", beego.AppConfig.String("requirepass")) defer conn.Close() //判断是否已经存在该分类 categoryKeys, err := redis.Values(conn.Do("HKEYS", "category")) if err != nil { return err } for _, categoryKey := range categoryKeys { categoryKeyStr := string(categoryKey.([]byte)) if strings.Contains(categoryKeyStr, "_Title") { titleValue, _ := conn.Do("HGET", "category", categoryKeyStr) if string(titleValue.([]byte)) == name { return nil } } } //新增一个分类 guid, _ := conn.Do("HINCRBY", "category", "guid", 1) //生成Guid,并保存到键category的guid域 guidStr := strconv.FormatInt(int64(guid.(int64)), 10) timeNow := time.Now() conn.Do("HMSET", "category", guidStr+"_Id", guidStr, guidStr+"_Title", name, guidStr+"_Views", 0, guidStr+"_TopicCount", 0, guidStr+"_Created", timeNow.Format("2006-01-02 15:04:05"), guidStr+"_Updated", timeNow.Format("2006-01-02 15:04:05")) return nil }
// Incr increments the specified key. If the key did not exist, it sets it to 1 // and sets it to expire after the number of seconds specified by window. // // It returns the new count value and the number of remaining seconds, or an error // if the operation fails. func (r *redisStore) Incr(key string, window time.Duration) (int, int, error) { conn := r.pool.Get() defer conn.Close() if err := selectDB(r.db, conn); err != nil { return 0, 0, err } // Atomically increment and read the TTL. conn.Send("MULTI") conn.Send("INCR", r.prefix+key) conn.Send("TTL", r.prefix+key) vals, err := redis.Values(conn.Do("EXEC")) if err != nil { conn.Do("DISCARD") return 0, 0, err } var cnt, ttl int if _, err = redis.Scan(vals, &cnt, &ttl); err != nil { return 0, 0, err } // If there was no TTL set, then this is a newly created key (INCR creates the key // if it didn't exist), so set it to expire. if ttl == -1 { ttl = int(window.Seconds()) _, err = conn.Do("EXPIRE", r.prefix+key, ttl) if err != nil { return 0, 0, err } } return cnt, ttl, nil }
func (chat *Chat) Subscribe() { psc := redis.PubSubConn{pool.Get()} psc.Subscribe("chat") c := pool.Get() for { switch v := psc.Receive().(type) { case redis.Message: log.Printf("%s: message %s\n", v.Channel, v.Data) id, err := redis.Int(v.Data, nil) if err != nil { log.Println(err) return } result, err := redis.Values(c.Do("HGETALL", "message:"+strconv.Itoa(id))) if err != nil { log.Println(err) return } var message Message err = redis.ScanStruct(result, &message) if err != nil { log.Println(err) return } chat.outgoing <- &message case redis.Subscription: log.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count) case error: log.Println(v) return } } }