From 9d5b02ec5062a23665ec596ef7d3efe4f5abcc27 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Fri, 29 Jun 2018 15:52:12 +0800 Subject: Add :expires_in option support for RedisCacheStore increment/decrement method. --- activesupport/CHANGELOG.md | 11 ++++++++++ .../lib/active_support/cache/redis_cache_store.rb | 24 ++++++++++++++++++++-- .../test/cache/stores/redis_cache_store_test.rb | 24 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 100d57aa16..8031d351a9 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -131,5 +131,16 @@ *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. diff --git a/activesupport/lib/active_support/cache/redis_cache_store.rb b/activesupport/lib/active_support/cache/redis_cache_store.rb index 11c574258f..95f8f639e8 100644 --- a/activesupport/lib/active_support/cache/redis_cache_store.rb +++ b/activesupport/lib/active_support/cache/redis_cache_store.rb @@ -256,9 +256,19 @@ module ActiveSupport # # 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 - redis.with { |c| c.incrby normalize_key(name, options), amount } + redis.with do |c| + val = c.incrby key, amount + if expires_in > 0 && c.ttl(key) == -2 + c.expire key, expires_in + end + val + end end end end @@ -272,9 +282,19 @@ module ActiveSupport # # 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 - redis.with { |c| c.decrby normalize_key(name, options), amount } + redis.with do |c| + val = c.decrby key, amount + if expires_in > 0 && c.ttl(key) == -2 + c.expire key, expires_in + end + val + end end end end diff --git a/activesupport/test/cache/stores/redis_cache_store_test.rb b/activesupport/test/cache/stores/redis_cache_store_test.rb index 24c4c5c481..a2165e1978 100644 --- a/activesupport/test/cache/stores/redis_cache_store_test.rb +++ b/activesupport/test/cache/stores/redis_cache_store_test.rb @@ -141,6 +141,30 @@ module ActiveSupport::Cache::RedisCacheStoreTests end end end + + def test_increment_expires_in + assert_called_with @cache.redis, :incrby, [ "#{@namespace}:foo", 1 ] do + assert_called_with @cache.redis, :expire, [ "#{@namespace}:foo", 60 ] do + @cache.increment("foo", 1, expires_in: 60) + end + end + + assert_not_called @cache.redis, :expire do + @cache.decrement("foo", 1, expires_in: 60) + end + end + + def test_decrement_expires_in + assert_called_with @cache.redis, :decrby, [ "#{@namespace}:foo", 1 ] do + assert_called_with @cache.redis, :expire, [ "#{@namespace}:foo", 60 ] do + @cache.decrement("foo", 1, expires_in: 60) + end + end + + assert_not_called @cache.redis, :expire do + @cache.decrement("foo", 1, expires_in: 60) + end + end end class ConnectionPoolBehaviourTest < StoreTest -- cgit v1.2.3