From 9a29c49fac1577b3c2cfba9a0b7ef2a09aa8076d Mon Sep 17 00:00:00 2001 From: tepinly Date: Mon, 25 Nov 2024 00:06:25 +0200 Subject: [PATCH 1/3] Added cache refresh rate to single fetches --- Gemfile.lock | 1 + lib/identity_cache/cache_fetcher.rb | 13 ++++++++++++- test/cache_fetcher_test.rb | 24 ++++++++++++++++++++++++ test/helpers/database_connection.rb | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8b4f6d11..de982bbe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -93,6 +93,7 @@ GEM PLATFORMS arm64-darwin-22 arm64-darwin-23 + arm64-darwin-24 x86_64-linux DEPENDENCIES diff --git a/lib/identity_cache/cache_fetcher.rb b/lib/identity_cache/cache_fetcher.rb index 3573a628..ecb543c0 100644 --- a/lib/identity_cache/cache_fetcher.rb +++ b/lib/identity_cache/cache_fetcher.rb @@ -1,8 +1,12 @@ # frozen_string_literal: true +require "time" require "securerandom" module IdentityCache + mattr_accessor :cache_refresh_period + self.cache_refresh_period = 60 + class CacheFetcher attr_accessor :cache_backend @@ -93,7 +97,10 @@ def fetch_without_fill_lock(key) data = nil upsert(key) do |value| value = nil if value == IdentityCache::DELETED || FillLock.cache_value?(value) - unless value.nil? + unless value.nil? || + (value&.is_a?(Hash) && + value[:cached_at] && + ((Time.now - value[:cached_at]) / 60).round > IdentityCache.cache_refresh_period) return value end @@ -316,6 +323,10 @@ def add_multi(keys) def add(key, value, expiration_options = EMPTY_HASH) return false unless IdentityCache.should_fill_cache? + if value&.is_a?(Hash) + value.merge(cached_at: Time.now.to_s) + end + @cache_backend.write(key, value, { unless_exist: true, **expiration_options }) end end diff --git a/test/cache_fetcher_test.rb b/test/cache_fetcher_test.rb index dcb0b4b6..8d3c6268 100644 --- a/test/cache_fetcher_test.rb +++ b/test/cache_fetcher_test.rb @@ -177,3 +177,27 @@ def other_cache_fetcher @other_cache_fetcher ||= IdentityCache::CacheFetcher.new(backend) end end + +def test_fetch_without_fill_lock_with_stale_cached_data + stale_time = Time.now - (IdentityCache.cache_refresh_period + 1) * 60 + backend.write(key, { cached_at: stale_time, data: :old_data }) + assert_memcache_operations(2) do + assert_equal(:new_data, cache_fetcher.fetch_without_fill_lock(key) { :new_data }) + end +end + +def test_fetch_without_fill_lock_with_fresh_cached_data + fresh_time = Time.now - (IdentityCache.cache_refresh_period - 1) * 60 + cached_data = { cached_at: fresh_time, data: :fresh_data } + backend.write(key, cached_data) + assert_memcache_operations(1) do + assert_equal(cached_data, cache_fetcher.fetch_without_fill_lock(key) { :new_data }) + end +end + +def test_fetch_without_fill_lock_with_non_hash_value + backend.write(key, "string_value") + assert_memcache_operations(1) do + assert_equal("string_value", cache_fetcher.fetch_without_fill_lock(key) { :new_data }) + end +end diff --git a/test/helpers/database_connection.rb b/test/helpers/database_connection.rb index 297a8574..eb0e1ffe 100644 --- a/test/helpers/database_connection.rb +++ b/test/helpers/database_connection.rb @@ -79,6 +79,7 @@ def create_tables "host" => ENV["MYSQL_HOST"] || "127.0.0.1", "username" => "root", "port" => ENV["MYSQL_PORT"] ? Integer(ENV["MYSQL_PORT"]) : 3306, + "password" => ENV["MYSQL_PASSWORD"] || "my-secret-pw", }, "postgresql" => { "adapter" => "postgresql", From 1c170cfcedbfc18a3cd2206dc4672ed3dc40add4 Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 16 Jan 2025 16:08:13 +0200 Subject: [PATCH 2/3] Updated tests --- Gemfile.lock | 1 + test/cache_fetcher_test.rb | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index de982bbe..337b3be9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -94,6 +94,7 @@ PLATFORMS arm64-darwin-22 arm64-darwin-23 arm64-darwin-24 + x64-mingw-ucrt x86_64-linux DEPENDENCIES diff --git a/test/cache_fetcher_test.rb b/test/cache_fetcher_test.rb index 8d3c6268..7ca97020 100644 --- a/test/cache_fetcher_test.rb +++ b/test/cache_fetcher_test.rb @@ -179,7 +179,9 @@ def other_cache_fetcher end def test_fetch_without_fill_lock_with_stale_cached_data - stale_time = Time.now - (IdentityCache.cache_refresh_period + 1) * 60 + identity_cache = IdentityCache + identity_cache.cache_refresh_period = 60 + stale_time = Time.now - (identity_cache.cache_refresh_period + 1) * 60 backend.write(key, { cached_at: stale_time, data: :old_data }) assert_memcache_operations(2) do assert_equal(:new_data, cache_fetcher.fetch_without_fill_lock(key) { :new_data }) @@ -187,7 +189,9 @@ def test_fetch_without_fill_lock_with_stale_cached_data end def test_fetch_without_fill_lock_with_fresh_cached_data - fresh_time = Time.now - (IdentityCache.cache_refresh_period - 1) * 60 + identity_cache = IdentityCache + identity_cache.cache_refresh_period = 60 + fresh_time = Time.now - (identity_cache.cache_refresh_period - 1) * 60 cached_data = { cached_at: fresh_time, data: :fresh_data } backend.write(key, cached_data) assert_memcache_operations(1) do From d99274cdb8e68d51b06d7b45196d003c4d4cc3cb Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 16 Jan 2025 21:06:24 +0200 Subject: [PATCH 3/3] Added 1.6.4 to changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b3a3ec5..c19ccc12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 1.6.4 + +- Add `cache_refresh_period` to allow for cache refresh after a period of time. (#579) + ## 1.6.3 - Split the `with_deferred_parent_expiration` and `with_deferred_parent_expiration`. (#578)