Example #1
0
// incrementOffset is a common incrementor method used between Increment and
// Decrement. If the key isn't set before, we will set the initial value. If
// there is a value present, we will add the given offset to that value and
// update the value with the new TTL.
func (c *Cache) incrementOffset(key string, initial, offset, ttl int64) error {
	c.client.Do("WATCH", key)

	if err := c.exists(key); err != nil {
		c.client.Do("MULTI")
		defer c.client.Do("EXEC")
		return c.Set(key, encoding.Int64Bytes(initial), ttl)
	}

	getValue, _, err := c.Get(key)
	if err != nil {
		return err
	}

	val, ok := encoding.BytesInt64(getValue)

	if !ok {
		return errors.NewEncoding(key)
	}

	// We are watching our key. With using a transaction, we can check that this
	// increment doesn't inflect with another concurrent request that might
	// happen.
	c.client.Do("MULTI")
	defer c.client.Do("EXEC")

	val += offset
	if val < 0 {
		return errors.NewValueBelowZero(key)
	}

	return c.Set(key, encoding.Int64Bytes(val), ttl)
}
Example #2
0
// incrementOffset is a common incrementor method used between Increment and
// Decrement. If the key isn't set before, we will set the initial value. If
// there is a value present, we will add the given offset to that value and
// update the value with the new TTL.
func (c *Cache) incrementOffset(key string, initial, offset, ttl int64) error {
	if err := c.exists(key); err != nil {
		return c.Set(key, encoding.Int64Bytes(initial), ttl)
	}

	val, ok := encoding.BytesInt64(c.items[key].value)

	if !ok {
		return errors.NewEncoding(key)
	}

	val += offset
	if val < 0 {
		return errors.NewValueBelowZero(key)
	}

	return c.Set(key, encoding.Int64Bytes(val), ttl)
}