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
func TestCache_Increment(t *testing.T) {
	for _, cache := range testDrivers() {
		cache.Increment("key1", 0, 1, 0)
		cache.Increment("key1", 0, 1, 0)
		v, _, _ := cache.Get("key1")

		num, _ := encoding.BytesInt64(v)
		if num != 1 {
			tests.FailMsg(t, cache, "Expected the value to be 1, got %d", num)
		}

		cache.Set("key2", []byte("string value, not incrementable"), 0)
		err := cache.Increment("key2", 0, 5, 0)
		if err == nil {
			tests.FailMsg(t, cache, "Expected the error not to be nil")
		}
	}
}
Example #3
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)
}
func ExampleDecrement() {
	cacher.Flush()
	cacher.Decrement("key1", 10, 1, 0)
	cacher.Decrement("key1", 10, 3, 0)
	v, _, _ := cacher.Get("key1")

	num, _ := encoding.BytesInt64(v)
	fmt.Println(num)

	cacher.Set("key2", []byte("string value, not decrementable"), 0)
	ok := cacher.Decrement("key2", 0, 5, 0)
	v2, _, _ := cacher.Get("key2")
	fmt.Println(ok, string(v2))

	// Output:
	// 7
	// Value for key `key2` could not be encoded. string value, not decrementable
}
Example #5
0
// Compare compares a cached value given by the cache and the key to the value
// passed in as an interface. If the values do not match, the given test will
// receive a `FailNow()` call and print an appropiate error message.
func Compare(t *testing.T, cache cacher.Cacher, key string, value interface{}) {
	_, ok := value.(int)
	if ok {
		val := int64(value.(int))
		v, _, _ := cache.Get(key)
		valInt, _ := encoding.BytesInt64(v)
		if valInt != val {
			msg := "Expected `" + key + "` to equal `" + strconv.FormatInt(val, 10) + "`, is `" + strconv.FormatInt(valInt, 10) + "`"
			FailMsg(t, cache, msg)
		}
	} else {
		value = value.(string)
		if v, _, _ := cache.Get(key); string(v) != value {
			msg := "Expected `" + key + "` to equal `" + value.(string) + "`"
			FailMsg(t, cache, msg)
		}
	}
}