Exemplo n.º 1
0
// 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
}
Exemplo n.º 2
0
// 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
}
Exemplo n.º 3
0
// 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)
}
Exemplo n.º 4
0
// 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
}
Exemplo n.º 5
0
// 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
}
Exemplo n.º 6
0
// 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
}