Skip to content

Commit

Permalink
Add support for globally resetting all ttl memoized values (#15)
Browse files Browse the repository at this point in the history
Track an index which causes immediate reset of memoized values every
time it is incremented.
  • Loading branch information
danielwestendorf authored Sep 18, 2024
1 parent e63c950 commit 3a3ab51
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
10 changes: 10 additions & 0 deletions lib/ttl_memoizeable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ module TTLMemoizeable
TTLMemoizationError = Class.new(StandardError)
SetupMutex = Mutex.new

@ttl_index = 0
@disabled = false

def self.disable!
@disabled = true
end

def self.reset!
@ttl_index += 1
end

def ttl_memoized_method(method_name, ttl: 1000)
raise TTLMemoizationError, "Method not defined: #{method_name}" unless method_defined?(method_name) || private_method_defined?(method_name)

Expand All @@ -23,6 +28,7 @@ def ttl_memoized_method(method_name, ttl: 1000)
expired_ttl = time_based_ttl ? 1.year.ago : 1

ttl_variable_name = :"@_ttl_for_#{ivar_name}"
ttl_index_variable_name = :"@_ttl_index_for_#{ivar_name}"
mutex_variable_name = :"@_mutex_for_#{ivar_name}"
value_variable_name = :"@_value_for_#{ivar_name}"

Expand Down Expand Up @@ -67,6 +73,7 @@ def ttl_memoized_method(method_name, ttl: 1000)

define_method ttl_exceeded_method_name do
return true if TTLMemoizeable.instance_variable_get(:@disabled)
return true if TTLMemoizeable.instance_variable_get(:@ttl_index) != instance_variable_get(ttl_index_variable_name)
return true unless instance_variable_defined?(value_variable_name)

compared_to = time_based_ttl ? ttl.ago : 0
Expand All @@ -92,6 +99,9 @@ def ttl_memoized_method(method_name, ttl: 1000)
if send(ttl_exceeded_method_name)
send(extend_ttl_method_name)

# Synchronize the ttl index to match the module's value
instance_variable_set(ttl_index_variable_name, TTLMemoizeable.instance_variable_get(:@ttl_index))

# Refresh value from the original method
instance_variable_set(value_variable_name, super())
end
Expand Down
24 changes: 24 additions & 0 deletions spec/ttl_memoizeable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -347,4 +347,28 @@ def bar
end
end
end

describe ".reset!" do
context "expires all ttls" do
let(:klass) { integer_ttl_klass }

it "only calls #expensive_bar twice" do
expect(Klass).to receive(:expensive_bar).and_call_original.exactly(3)

expect(Klass.bar).to eq(1) # first expensive_bar

described_class.reset!
expect(Klass.bar).to eq(1) # second expensive_bar
2.times do
expect(Klass.bar).to eq(1)
end

described_class.reset!
expect(Klass.bar).to eq(1) # third expensive_bar
8.times do
expect(Klass.bar).to eq(1)
end
end
end
end
end

0 comments on commit 3a3ab51

Please sign in to comment.