// CompareAndReplace validates the token with the token in the store. If the // tokens match, we will replace the value and return true. If it doesn't, we // will not replace the value and return false. func (c *Cache) CompareAndReplace(token, key string, value []byte, ttl int64) error { c.client.Do("WATCH", key) defer c.client.Do("UNWATCH") if err := c.exists(key); err != nil { return err } _, storedToken, _ := c.Get(key) if token != storedToken { return errors.NewNotFound(key) } // We're watching the key, by using MULTI the transaction will fail if the key // changes in the meantime. c.client.Do("MULTI") c.Set(key, value, ttl) rValue, _ := c.client.Do("EXEC") for _, v := range rValue.([]interface{}) { if v.(string) != "OK" { return errors.NewNotFound(key) } } return nil }
// Replace will update and only update the value of a cache key. If the key is // not previously used, we will return false. func (c *Cache) Replace(key string, value []byte, ttl int64) error { c.client.Do("WATCH", key) defer c.client.Do("UNWATCH") if err := c.exists(key); err != nil { return err } // We're watching the key, so we can use a transaction to set the value. If // the key changes in the meantime, it'll fail. c.client.Do("MULTI") c.Set(key, value, ttl) vals, err := c.client.Do("EXEC") if err != nil { return err } for _, v := range vals.([]interface{}) { if v.(string) != "OK" { return errors.NewNotFound(key) } } return nil }
// Delete will validate if the key actually is stored in the cache. If it is // stored, it will remove the item from the cache. If it is not stored, it will // return false. func (c *Cache) Delete(key string) error { for i, v := range c.keys { if v == key { return c.removeAt(i) } } return errors.NewNotFound(key) }
// Delete will validate if the key actually is stored in the cache. If it is // stored, it will remove the item from the cache. If it is not stored, it will // return false. func (c *Cache) Delete(key string) error { v, err := c.client.Do("DEL", key) if err != nil { return err } if v.(int64) != 1 { errors.NewNotFound(key) } return nil }
// Get gets the value out of the map associated with the provided key. func (c *Cache) Get(key string) ([]byte, string, error) { value, err := c.client.Do("GET", key) if err != nil { return []byte{}, "", err } if value == nil { return []byte{}, "", errors.NewNotFound(key) } val, ok := value.([]byte) if !ok { return nil, "", errors.NewInvalidData(key) } return val, encoding.Md5Sum(val), nil }
// GetMulti gets multiple values from the cache and returns them as a map. It // uses `Get` internally to retrieve the data. func (c *Cache) GetMulti(keys []string) (map[string][]byte, map[string]string, map[string]error) { cValues, err := c.client.Do("MGET", keyArgs(keys)...) items := make(map[string][]byte) errs := make(map[string]error) tokens := make(map[string]string) for _, v := range keys { errs[v] = errors.NewNotFound(v) } if err == nil { values := cValues.([]interface{}) for i, val := range values { byteVal, ok := val.([]byte) if ok { items[keys[i]] = byteVal tokens[keys[i]] = encoding.Md5Sum(items[keys[i]]) errs[keys[i]] = nil } } } return items, tokens, errs }