Skip to content

Commit 4a07e6a

Browse files
committed
Add mechanism to prevent nested blocks
This could have caused the cache to have been overwritten
1 parent a86bf5b commit 4a07e6a

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

lib/identity_cache.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ class AssociationError < StandardError; end
6060

6161
class InverseAssociationError < StandardError; end
6262

63+
class NestedDeferredParentBlockError < StandardError; end
64+
6365
class UnsupportedScopeError < StandardError; end
6466

6567
class UnsupportedAssociationError < StandardError; end
@@ -199,6 +201,7 @@ def with_deferred_parent_expiration
199201

200202
yield
201203

204+
Thread.current[:deferred_parent_expiration] = nil
202205
Thread.current[:parent_records_for_cache_expiry].each(&:expire_primary_index)
203206
end
204207

test/index_cache_test.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,32 @@ def test_with_deferred_parent_expiration
191191
assert_operator(@memcached_spy.calls.count, :>, 0)
192192
assert_equal(expected_item_expiration_count, item_expiration_count)
193193
assert_equal(expected_associated_record_expiration_count, associated_record_expiration_count)
194+
ensure
195+
Thread.current[:deferred_parent_expiration] = nil
196+
end
197+
198+
def test_double_nested_deferred_parent_expiration
199+
Item.send(:cache_has_many, :associated_records, embed: true)
200+
201+
@parent = Item.create!(title: "bob")
202+
@records = @parent.associated_records.create!([{ name: "foo" }, { name: "bar" }, { name: "baz" }])
203+
204+
@memcached_spy = Spy.on(backend, :write).and_call_through
205+
206+
assert_raises(IdentityCache::NestedDeferredParentBlockError) do
207+
IdentityCache.with_deferred_parent_expiration do
208+
IdentityCache.with_deferred_parent_expiration do
209+
@parent.transaction do
210+
@parent.associated_records.destroy_all
211+
end
212+
assert_equal(expected_associated_record_expiration_count, @memcached_spy.calls.count)
213+
end
214+
end
215+
end
216+
217+
assert_equal(0, @memcached_spy.calls.count)
218+
ensure
219+
Thread.current[:deferred_parent_expiration] = nil
194220
end
195221

196222
def test_deep_association_with_deferred_parent_expiration
@@ -228,6 +254,8 @@ def test_deep_association_with_deferred_parent_expiration
228254
assert_equal(expected_item_expiration_count, item_expiration_count)
229255
assert_equal(expected_associated_record_expiration_count, associated_record_expiration_count)
230256
assert_equal(expected_deeply_associated_record_expiration_count, deeply_associated_record_expiration_count)
257+
ensure
258+
Thread.current[:deferred_parent_expiration] = nil
231259
end
232260

233261
private

0 commit comments

Comments
 (0)