Skip to content

Commit

Permalink
Add mechanism to prevent nested blocks
Browse files Browse the repository at this point in the history
This could have caused the cache to have been overwritten
  • Loading branch information
Stivaros committed Jun 10, 2024
1 parent a86bf5b commit 4a07e6a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/identity_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class AssociationError < StandardError; end

class InverseAssociationError < StandardError; end

class NestedDeferredParentBlockError < StandardError; end

class UnsupportedScopeError < StandardError; end

class UnsupportedAssociationError < StandardError; end
Expand Down Expand Up @@ -199,6 +201,7 @@ def with_deferred_parent_expiration

yield

Thread.current[:deferred_parent_expiration] = nil
Thread.current[:parent_records_for_cache_expiry].each(&:expire_primary_index)
end

Expand Down
28 changes: 28 additions & 0 deletions test/index_cache_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,32 @@ def test_with_deferred_parent_expiration
assert_operator(@memcached_spy.calls.count, :>, 0)
assert_equal(expected_item_expiration_count, item_expiration_count)
assert_equal(expected_associated_record_expiration_count, associated_record_expiration_count)
ensure
Thread.current[:deferred_parent_expiration] = nil
end

def test_double_nested_deferred_parent_expiration
Item.send(:cache_has_many, :associated_records, embed: true)

@parent = Item.create!(title: "bob")
@records = @parent.associated_records.create!([{ name: "foo" }, { name: "bar" }, { name: "baz" }])

@memcached_spy = Spy.on(backend, :write).and_call_through

assert_raises(IdentityCache::NestedDeferredParentBlockError) do
IdentityCache.with_deferred_parent_expiration do
IdentityCache.with_deferred_parent_expiration do
@parent.transaction do
@parent.associated_records.destroy_all
end
assert_equal(expected_associated_record_expiration_count, @memcached_spy.calls.count)
end
end
end

assert_equal(0, @memcached_spy.calls.count)
ensure
Thread.current[:deferred_parent_expiration] = nil
end

def test_deep_association_with_deferred_parent_expiration
Expand Down Expand Up @@ -228,6 +254,8 @@ def test_deep_association_with_deferred_parent_expiration
assert_equal(expected_item_expiration_count, item_expiration_count)
assert_equal(expected_associated_record_expiration_count, associated_record_expiration_count)
assert_equal(expected_deeply_associated_record_expiration_count, deeply_associated_record_expiration_count)
ensure
Thread.current[:deferred_parent_expiration] = nil
end

private
Expand Down

0 comments on commit 4a07e6a

Please sign in to comment.