Firstly, increment and decrement shouldn't care about the particulars of
key expiry. They should only know that they have to pass that responsibility
on to somewhere else.

Secondly, it moves the key normalization back inside the instrumentation like
it was originally. I think that matches the original design intention or at
the very least it lets users catch haywire key truncation.

Thirdly, it moves the changelog entry to the top of the file, where new entries
go. I couldn't understand what the entry was saying so I tried to rewrite it.
This commit is contained in:
Kasper Timm Hansen 2018-07-01 12:42:18 +02:00
parent f666fb58a3
commit 969577d960
No known key found for this signature in database
GPG Key ID: 191153215EDA53D8
3 changed files with 28 additions and 29 deletions

@ -1,3 +1,13 @@
* RedisCacheStore: support key expiry in increment/decrement.
Pass `:expires_in` to `#increment` and `#decrement` to set a Redis EXPIRE on the key.
If the key is already set to expire, RedisCacheStore won't extend its expiry.
Rails.cache.increment("some_key", 1, expires_in: 2.minutes)
*Jason Lee*
* Allow Range#=== and Range#cover? on Range
`Range#cover?` can now accept a range argument like `Range#include?` and
@ -131,16 +141,5 @@
*Eileen M. Uchitelle*, *Aaron Patterson*
* RedisCacheStore: Support expiring counters.
Pass `expires_in: [seconds]` to `#increment` and `#decrement` options
to set the Redis EXPIRE if the counter doesn't exist.
If the counter exists, Redis doesn't extend its expiry when it's exist.
```
Rails.cache.increment("my_counter", 1, expires_in: 2.minutes)
```
*Jason Lee*
Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/activesupport/CHANGELOG.md) for previous changes.

@ -256,18 +256,15 @@ def delete_matched(matcher, options = nil)
#
# Failsafe: Raises errors.
def increment(name, amount = 1, options = nil)
options = merged_options(options)
key = normalize_key(name, options)
expires_in = options[:expires_in].to_i
instrument :increment, name, amount: amount do
failsafe :increment do
options = merged_options(options)
key = normalize_key(name, options)
redis.with do |c|
val = c.incrby key, amount
if expires_in > 0 && c.ttl(key) < 0
c.expire key, expires_in
c.incrby(key, amount).tap do
write_key_expiry(c, key, options)
end
val
end
end
end
@ -282,18 +279,15 @@ def increment(name, amount = 1, options = nil)
#
# Failsafe: Raises errors.
def decrement(name, amount = 1, options = nil)
options = merged_options(options)
key = normalize_key(name, options)
expires_in = options[:expires_in].to_i
instrument :decrement, name, amount: amount do
failsafe :decrement do
options = merged_options(options)
key = normalize_key(name, options)
redis.with do |c|
val = c.decrby key, amount
if expires_in > 0 && c.ttl(key) < 0
c.expire key, expires_in
c.decrby(key, amount).tap do
write_key_expiry(c, key, options)
end
val
end
end
end
@ -405,6 +399,12 @@ def write_entry(key, entry, unless_exist: false, raw: false, expires_in: nil, ra
end
end
def write_key_expiry(client, key, options)
if options[:expires_in] && client.ttl(key).negative?
client.expire key, options[:expires_in].to_i
end
end
# Delete an entry from the cache.
def delete_entry(key, options)
failsafe :delete_entry, returning: false do

@ -152,7 +152,7 @@ def test_increment_expires_in
# key and ttl exist
@cache.redis.setex "#{@namespace}:bar", 120, 1
assert_not_called @cache.redis, :expire do
@cache.increment "bar", 1, expires_in: 120
@cache.increment "bar", 1, expires_in: 2.minutes
end
# key exist but not have expire
@ -172,7 +172,7 @@ def test_decrement_expires_in
# key and ttl exist
@cache.redis.setex "#{@namespace}:bar", 120, 1
assert_not_called @cache.redis, :expire do
@cache.decrement "bar", 1, expires_in: 120
@cache.decrement "bar", 1, expires_in: 2.minutes
end
# key exist but not have expire