mirror of https://github.com/rails/rails
Add initial value support to MemCacheStore #increment and #decrement
This commit is contained in:
parent
fe8d41eda1
commit
f48bf3975f
|
@ -1,3 +1,11 @@
|
|||
* Allow #increment and #decrement methods of `ActiveSupport::Cache::Store`
|
||||
subclasses to set new values.
|
||||
|
||||
Previously incrementing or decrementing an unset key would fail and return
|
||||
nil. A default will now be assumed and the key will be created.
|
||||
|
||||
*Andrej Blagojević*, *Eugene Kenny*
|
||||
|
||||
* Add `skip_nil:` support to `RedisCacheStore`
|
||||
|
||||
*Joey Paris*
|
||||
|
|
|
@ -43,14 +43,33 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
# Increments an already existing integer value that is stored in the cache.
|
||||
# If the key is not found nothing is done.
|
||||
# Increment a cached integer value. Returns the updated value.
|
||||
#
|
||||
# If the key is unset, it starts from +0+:
|
||||
#
|
||||
# cache.increment("foo") # => 1
|
||||
# cache.increment("bar", 100) # => 100
|
||||
#
|
||||
# To set a specific value, call #write:
|
||||
#
|
||||
# cache.write("baz", 5)
|
||||
# cache.increment("baz") # => 6
|
||||
#
|
||||
def increment(name, amount = 1, options = nil)
|
||||
modify_value(name, amount, options)
|
||||
end
|
||||
|
||||
# Decrements an already existing integer value that is stored in the cache.
|
||||
# If the key is not found nothing is done.
|
||||
# Decrement a cached integer value. Returns the updated value.
|
||||
#
|
||||
# If the key is unset, it will be set to +-amount+.
|
||||
#
|
||||
# cache.decrement("foo") # => -1
|
||||
#
|
||||
# To set a specific value, call #write:
|
||||
#
|
||||
# cache.write("baz", 5)
|
||||
# cache.decrement("baz") # => 4
|
||||
#
|
||||
def decrement(name, amount = 1, options = nil)
|
||||
modify_value(name, -amount, options)
|
||||
end
|
||||
|
@ -179,8 +198,8 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
# Modifies the amount of an already existing integer value that is stored in the cache.
|
||||
# If the key is not found nothing is done.
|
||||
# Modifies the amount of an integer value that is stored in the cache.
|
||||
# If the key is not found it is created and set to +amount+.
|
||||
def modify_value(name, amount, options)
|
||||
file_name = normalize_key(name, options)
|
||||
|
||||
|
@ -191,6 +210,9 @@ module ActiveSupport
|
|||
num = num.to_i + amount
|
||||
write(name, num, options)
|
||||
num
|
||||
else
|
||||
write(name, Integer(amount), options)
|
||||
amount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -129,28 +129,50 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
# Increment a cached value. This method uses the memcached incr atomic
|
||||
# operator and can only be used on values written with the +:raw+ option.
|
||||
# Calling it on a value not stored with +:raw+ will initialize that value
|
||||
# to zero.
|
||||
# Increment a cached integer value using the memcached incr atomic operator.
|
||||
# Returns the updated value.
|
||||
#
|
||||
# If the key is unset or has expired, it will be set to +amount+:
|
||||
#
|
||||
# cache.increment("foo") # => 1
|
||||
# cache.increment("bar", 100) # => 100
|
||||
#
|
||||
# To set a specific value, call #write passing <tt>raw: true</tt>:
|
||||
#
|
||||
# cache.write("baz", 5, raw: true)
|
||||
# cache.increment("baz") # => 6
|
||||
#
|
||||
# Incrementing a non-numeric value, or a value written without
|
||||
# <tt>raw: true</tt>, will fail and return +nil+.
|
||||
def increment(name, amount = 1, options = nil)
|
||||
options = merged_options(options)
|
||||
instrument(:increment, name, amount: amount) do
|
||||
rescue_error_with nil do
|
||||
@data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in]) }
|
||||
@data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in], amount) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Decrement a cached value. This method uses the memcached decr atomic
|
||||
# operator and can only be used on values written with the +:raw+ option.
|
||||
# Calling it on a value not stored with +:raw+ will initialize that value
|
||||
# to zero.
|
||||
# Decrement a cached integer value using the memcached decr atomic operator.
|
||||
# Returns the updated value.
|
||||
#
|
||||
# If the key is unset or has expired, it will be set to 0. Memcached
|
||||
# does not support negative counters.
|
||||
#
|
||||
# cache.decrement("foo") # => 0
|
||||
#
|
||||
# To set a specific value, call #write passing <tt>raw: true</tt>:
|
||||
#
|
||||
# cache.write("baz", 5, raw: true)
|
||||
# cache.decrement("baz") # => 4
|
||||
#
|
||||
# Decrementing a non-numeric value, or a value written without
|
||||
# <tt>raw: true</tt>, will fail and return +nil+.
|
||||
def decrement(name, amount = 1, options = nil)
|
||||
options = merged_options(options)
|
||||
instrument(:decrement, name, amount: amount) do
|
||||
rescue_error_with nil do
|
||||
@data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in]) }
|
||||
@data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in], 0) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -108,12 +108,33 @@ module ActiveSupport
|
|||
@pruning
|
||||
end
|
||||
|
||||
# Increment an integer value in the cache.
|
||||
# Increment a cached integer value. Returns the updated value.
|
||||
#
|
||||
# If the key is unset, it will be set to +amount+:
|
||||
#
|
||||
# cache.increment("foo") # => 1
|
||||
# cache.increment("bar", 100) # => 100
|
||||
#
|
||||
# To set a specific value, call #write:
|
||||
#
|
||||
# cache.write("baz", 5)
|
||||
# cache.increment("baz") # => 6
|
||||
#
|
||||
def increment(name, amount = 1, options = nil)
|
||||
modify_value(name, amount, options)
|
||||
end
|
||||
|
||||
# Decrement an integer value in the cache.
|
||||
# Decrement a cached integer value. Returns the updated value.
|
||||
#
|
||||
# If the key is unset or has expired, it will be set to +-amount+.
|
||||
#
|
||||
# cache.decrement("foo") # => -1
|
||||
#
|
||||
# To set a specific value, call #write:
|
||||
#
|
||||
# cache.write("baz", 5)
|
||||
# cache.decrement("baz") # => 4
|
||||
#
|
||||
def decrement(name, amount = 1, options = nil)
|
||||
modify_value(name, -amount, options)
|
||||
end
|
||||
|
@ -188,6 +209,8 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
# Modifies the amount of an integer value that is stored in the cache.
|
||||
# If the key is not found it is created and set to +amount+.
|
||||
def modify_value(name, amount, options)
|
||||
options = merged_options(options)
|
||||
synchronize do
|
||||
|
@ -195,6 +218,9 @@ module ActiveSupport
|
|||
num = num.to_i + amount
|
||||
write(name, num, options)
|
||||
num
|
||||
else
|
||||
write(name, Integer(amount), options)
|
||||
amount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -235,12 +235,21 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
# Cache Store API implementation.
|
||||
# Increment a cached integer value using the Redis incrby atomic operator.
|
||||
# Returns the updated value.
|
||||
#
|
||||
# Increment a cached value. This method uses the Redis incr atomic
|
||||
# operator and can only be used on values written with the +:raw+ option.
|
||||
# Calling it on a value not stored with +:raw+ will initialize that value
|
||||
# to zero.
|
||||
# If the key is unset or has expired, it will be set to +amount+:
|
||||
#
|
||||
# cache.increment("foo") # => 1
|
||||
# cache.increment("bar", 100) # => 100
|
||||
#
|
||||
# To set a specific value, call #write passing <tt>raw: true</tt>:
|
||||
#
|
||||
# cache.write("baz", 5, raw: true)
|
||||
# cache.increment("baz") # => 6
|
||||
#
|
||||
# Incrementing a non-numeric value, or a value written without
|
||||
# <tt>raw: true</tt>, will fail and return +nil+.
|
||||
#
|
||||
# Failsafe: Raises errors.
|
||||
def increment(name, amount = 1, options = nil)
|
||||
|
@ -258,12 +267,20 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
# Cache Store API implementation.
|
||||
# Decrement a cached integer value using the Redis decrby atomic operator.
|
||||
# Returns the updated value.
|
||||
#
|
||||
# Decrement a cached value. This method uses the Redis decr atomic
|
||||
# operator and can only be used on values written with the +:raw+ option.
|
||||
# Calling it on a value not stored with +:raw+ will initialize that value
|
||||
# to zero.
|
||||
# If the key is unset or has expired, it will be set to -amount:
|
||||
#
|
||||
# cache.decrement("foo") # => -1
|
||||
#
|
||||
# To set a specific value, call #write passing <tt>raw: true</tt>:
|
||||
#
|
||||
# cache.write("baz", 5, raw: true)
|
||||
# cache.decrement("baz") # => 4
|
||||
#
|
||||
# Decrementing a non-numeric value, or a value written without
|
||||
# <tt>raw: true</tt>, will fail and return +nil+.
|
||||
#
|
||||
# Failsafe: Raises errors.
|
||||
def decrement(name, amount = 1, options = nil)
|
||||
|
|
|
@ -11,7 +11,9 @@ module CacheIncrementDecrementBehavior
|
|||
assert_equal 3, @cache.read(key, raw: true).to_i
|
||||
|
||||
missing = @cache.increment(SecureRandom.alphanumeric)
|
||||
assert(missing.nil? || missing == 1)
|
||||
assert_equal 1, missing
|
||||
missing = @cache.increment(SecureRandom.alphanumeric, 100)
|
||||
assert_equal 100, missing
|
||||
end
|
||||
|
||||
def test_decrement
|
||||
|
@ -24,6 +26,8 @@ module CacheIncrementDecrementBehavior
|
|||
assert_equal 1, @cache.read(key, raw: true).to_i
|
||||
|
||||
missing = @cache.decrement(SecureRandom.alphanumeric)
|
||||
assert(missing.nil? || missing == -1)
|
||||
assert_equal @cache.is_a?(ActiveSupport::Cache::MemCacheStore) ? 0 : -1, missing
|
||||
missing = @cache.decrement(SecureRandom.alphanumeric, 100)
|
||||
assert_equal @cache.is_a?(ActiveSupport::Cache::MemCacheStore) ? 0 : -100, missing
|
||||
end
|
||||
end
|
||||
|
|
|
@ -127,6 +127,11 @@ class MemCacheStoreTest < ActiveSupport::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_increment_unset_key
|
||||
assert_equal 1, @cache.increment("foo")
|
||||
assert_equal "1", @cache.read("foo", raw: true)
|
||||
end
|
||||
|
||||
def test_write_expires_at
|
||||
cache = lookup_store(raw: true, namespace: nil)
|
||||
|
||||
|
@ -139,14 +144,19 @@ class MemCacheStoreTest < ActiveSupport::TestCase
|
|||
|
||||
def test_increment_expires_in
|
||||
cache = lookup_store(raw: true, namespace: nil)
|
||||
assert_called_with client(cache), :incr, [ "foo", 1, 60 ] do
|
||||
assert_called_with client(cache), :incr, [ "foo", 1, 60, 1 ] do
|
||||
cache.increment("foo", 1, expires_in: 60)
|
||||
end
|
||||
end
|
||||
|
||||
def test_decrement_unset_key
|
||||
assert_equal 0, @cache.decrement("foo")
|
||||
assert_equal "0", @cache.read("foo", raw: true)
|
||||
end
|
||||
|
||||
def test_decrement_expires_in
|
||||
cache = lookup_store(raw: true, namespace: nil)
|
||||
assert_called_with client(cache), :decr, [ "foo", 1, 60 ] do
|
||||
assert_called_with client(cache), :decr, [ "foo", 1, 60, 0 ] do
|
||||
cache.decrement("foo", 1, expires_in: 60)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue