diff --git a/lib/prop/interval_strategy.rb b/lib/prop/interval_strategy.rb index c57cacd..78ce84e 100644 --- a/lib/prop/interval_strategy.rb +++ b/lib/prop/interval_strategy.rb @@ -21,7 +21,15 @@ def increment(cache_key, amount, options = {}) def decrement(cache_key, amount, options = {}) raise ArgumentError, "Change amount must be a Integer, was #{amount.class}" unless amount.is_a?(Integer) - cache.decrement(cache_key, amount, expires_in: options.fetch(:interval, nil)) || (cache.write(cache_key, 0, raw: true, expires_in: options.fetch(:interval, nil)) && 0) # WARNING: potential race condition + + new_value = cache.decrement(cache_key, amount, expires_in: options.fetch(:interval, nil)) + + # In ActiveSupport < 7.1, decrement on a new key does nothing and returns nil. + # In ActiveSupport >= 7.1, decrement on a new key sets its value to 0 first and then decrements, returning a negative value. + if new_value.nil? || new_value == -amount + # WARNING: potential race condition + cache.write(cache_key, 0, raw: true, expires_in: options.fetch(:interval, nil)) && 0 + end end def reset(cache_key, options = {}) diff --git a/test/helper.rb b/test/helper.rb index d9127a2..56db35a 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -11,6 +11,14 @@ require 'active_support/cache/memory_store' require 'active_support/notifications' +begin + require 'active_support/deprecation' + require 'active_support/deprecator' +rescue LoadError +end + +require 'active_support/core_ext/numeric/time' + Minitest::Test.class_eval do def setup_fake_store Prop.cache = ActiveSupport::Cache::MemoryStore.new