From ded8301375ef06102a528c809982cbb380b1ad04 Mon Sep 17 00:00:00 2001 From: fatkodima Date: Mon, 9 May 2022 18:12:14 +0300 Subject: [PATCH] Set ttl for redis and memcache cache stores when using `expires_at` --- activesupport/lib/active_support/cache.rb | 7 +++++++ .../test/cache/behaviors/cache_store_behavior.rb | 8 ++++++++ .../test/cache/stores/mem_cache_store_test.rb | 10 ++++++++++ .../test/cache/stores/redis_cache_store_test.rb | 5 +++++ 4 files changed, 30 insertions(+) diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 87712158048..bb297ef9bbb 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -678,6 +678,13 @@ module ActiveSupport def merged_options(call_options) if call_options call_options = normalize_options(call_options) + if call_options.key?(:expires_in) && call_options.key?(:expires_at) + raise ArgumentError, "Either :expires_in or :expires_at can be supplied, but not both" + end + + expires_at = call_options.delete(:expires_at) + call_options[:expires_in] = (expires_at - Time.now) if expires_at + if options.empty? call_options else diff --git a/activesupport/test/cache/behaviors/cache_store_behavior.rb b/activesupport/test/cache/behaviors/cache_store_behavior.rb index 9495b4521f8..8af0d40d826 100644 --- a/activesupport/test/cache/behaviors/cache_store_behavior.rb +++ b/activesupport/test/cache/behaviors/cache_store_behavior.rb @@ -536,6 +536,14 @@ module CacheStoreBehavior end end + def test_expires_in_and_expires_at + key = SecureRandom.uuid + error = assert_raises(ArgumentError) do + @cache.write(key, "bar", expire_in: 60, expires_at: 1.minute.from_now) + end + assert_equal "Either :expires_in or :expires_at can be supplied, but not both", error.message + end + def test_race_condition_protection_skipped_if_not_defined key = SecureRandom.alphanumeric @cache.write(key, "bar") diff --git a/activesupport/test/cache/stores/mem_cache_store_test.rb b/activesupport/test/cache/stores/mem_cache_store_test.rb index ef1acfe4f41..3bc07718fe9 100644 --- a/activesupport/test/cache/stores/mem_cache_store_test.rb +++ b/activesupport/test/cache/stores/mem_cache_store_test.rb @@ -127,6 +127,16 @@ class MemCacheStoreTest < ActiveSupport::TestCase end end + def test_write_expires_at + cache = lookup_store(raw: true, namespace: nil) + + Time.stub(:now, Time.now) do + assert_called_with client(cache), :set, [ "key_with_expires_at", "bar", 30 * 60, Hash ] do + cache.write("key_with_expires_at", "bar", expires_at: 30.minutes.from_now) + end + end + end + def test_increment_expires_in cache = lookup_store(raw: true, namespace: nil) assert_called_with client(cache), :incr, [ "foo", 1, 60 ] do diff --git a/activesupport/test/cache/stores/redis_cache_store_test.rb b/activesupport/test/cache/stores/redis_cache_store_test.rb index efe4c38aa22..3e4db684901 100644 --- a/activesupport/test/cache/stores/redis_cache_store_test.rb +++ b/activesupport/test/cache/stores/redis_cache_store_test.rb @@ -179,6 +179,11 @@ module ActiveSupport::Cache::RedisCacheStoreTests end end + def test_write_expires_at + @cache.write "key_with_expires_at", "bar", expires_at: 30.minutes.from_now + assert @cache.redis.ttl("#{@namespace}:key_with_expires_at") > 0 + 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