identity_cache 0.4.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/probots.yml +2 -0
- data/.github/workflows/ci.yml +92 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +5 -0
- data/CAVEATS.md +25 -0
- data/CHANGELOG.md +73 -19
- data/Gemfile +5 -1
- data/LICENSE +1 -1
- data/README.md +49 -27
- data/Rakefile +14 -5
- data/dev.yml +12 -16
- data/gemfiles/Gemfile.latest-release +8 -0
- data/gemfiles/Gemfile.min-supported +7 -0
- data/gemfiles/Gemfile.rails-edge +7 -0
- data/identity_cache.gemspec +29 -10
- data/lib/identity_cache.rb +78 -51
- data/lib/identity_cache/belongs_to_caching.rb +12 -40
- data/lib/identity_cache/cache_fetcher.rb +6 -5
- data/lib/identity_cache/cache_hash.rb +2 -2
- data/lib/identity_cache/cache_invalidation.rb +4 -11
- data/lib/identity_cache/cache_key_generation.rb +17 -65
- data/lib/identity_cache/cache_key_loader.rb +128 -0
- data/lib/identity_cache/cached.rb +7 -0
- data/lib/identity_cache/cached/association.rb +87 -0
- data/lib/identity_cache/cached/attribute.rb +123 -0
- data/lib/identity_cache/cached/attribute_by_multi.rb +37 -0
- data/lib/identity_cache/cached/attribute_by_one.rb +88 -0
- data/lib/identity_cache/cached/belongs_to.rb +100 -0
- data/lib/identity_cache/cached/embedded_fetching.rb +41 -0
- data/lib/identity_cache/cached/prefetcher.rb +61 -0
- data/lib/identity_cache/cached/primary_index.rb +96 -0
- data/lib/identity_cache/cached/recursive/association.rb +109 -0
- data/lib/identity_cache/cached/recursive/has_many.rb +9 -0
- data/lib/identity_cache/cached/recursive/has_one.rb +9 -0
- data/lib/identity_cache/cached/reference/association.rb +16 -0
- data/lib/identity_cache/cached/reference/has_many.rb +105 -0
- data/lib/identity_cache/cached/reference/has_one.rb +100 -0
- data/lib/identity_cache/configuration_dsl.rb +53 -215
- data/lib/identity_cache/encoder.rb +95 -0
- data/lib/identity_cache/expiry_hook.rb +36 -0
- data/lib/identity_cache/fallback_fetcher.rb +2 -1
- data/lib/identity_cache/load_strategy/eager.rb +28 -0
- data/lib/identity_cache/load_strategy/lazy.rb +71 -0
- data/lib/identity_cache/load_strategy/load_request.rb +20 -0
- data/lib/identity_cache/load_strategy/multi_load_request.rb +27 -0
- data/lib/identity_cache/mem_cache_store_cas.rb +53 -0
- data/lib/identity_cache/memoized_cache_proxy.rb +137 -58
- data/lib/identity_cache/parent_model_expiration.rb +46 -11
- data/lib/identity_cache/query_api.rb +102 -408
- data/lib/identity_cache/railtie.rb +8 -0
- data/lib/identity_cache/record_not_found.rb +6 -0
- data/lib/identity_cache/should_use_cache.rb +1 -0
- data/lib/identity_cache/version.rb +3 -2
- data/lib/identity_cache/with_primary_index.rb +136 -0
- data/lib/identity_cache/without_primary_index.rb +24 -3
- data/performance/cache_runner.rb +25 -73
- data/performance/cpu.rb +4 -3
- data/performance/externals.rb +4 -3
- data/performance/profile.rb +6 -5
- data/railgun.yml +16 -0
- metadata +60 -73
- data/.travis.yml +0 -30
- data/Gemfile.rails42 +0 -6
- data/Gemfile.rails50 +0 -6
- data/test/attribute_cache_test.rb +0 -110
- data/test/cache_fetch_includes_test.rb +0 -46
- data/test/cache_hash_test.rb +0 -14
- data/test/cache_invalidation_test.rb +0 -139
- data/test/deeply_nested_associated_record_test.rb +0 -19
- data/test/denormalized_has_many_test.rb +0 -211
- data/test/denormalized_has_one_test.rb +0 -160
- data/test/fetch_multi_test.rb +0 -308
- data/test/fetch_test.rb +0 -258
- data/test/fixtures/serialized_record.mysql2 +0 -0
- data/test/fixtures/serialized_record.postgresql +0 -0
- data/test/helpers/active_record_objects.rb +0 -106
- data/test/helpers/database_connection.rb +0 -72
- data/test/helpers/serialization_format.rb +0 -42
- data/test/helpers/update_serialization_format.rb +0 -24
- data/test/identity_cache_test.rb +0 -29
- data/test/index_cache_test.rb +0 -161
- data/test/memoized_attributes_test.rb +0 -49
- data/test/memoized_cache_proxy_test.rb +0 -107
- data/test/normalized_belongs_to_test.rb +0 -107
- data/test/normalized_has_many_test.rb +0 -231
- data/test/normalized_has_one_test.rb +0 -9
- data/test/prefetch_associations_test.rb +0 -364
- data/test/readonly_test.rb +0 -109
- data/test/recursive_denormalized_has_many_test.rb +0 -131
- data/test/save_test.rb +0 -82
- data/test/schema_change_test.rb +0 -112
- data/test/serialization_format_change_test.rb +0 -16
- data/test/test_helper.rb +0 -140
@@ -1,364 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class PrefetchAssociationsTest < IdentityCache::TestCase
|
4
|
-
NAMESPACE = IdentityCache.cache_namespace
|
5
|
-
|
6
|
-
def setup
|
7
|
-
super
|
8
|
-
@bob = Item.create!(:title => 'bob')
|
9
|
-
@joe = Item.create!(:title => 'joe')
|
10
|
-
@fred = Item.create!(:title => 'fred')
|
11
|
-
@bob_blob_key = "#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:1"
|
12
|
-
@joe_blob_key = "#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:2"
|
13
|
-
@fred_blob_key = "#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:3"
|
14
|
-
@tenth_blob_key = "#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:10"
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_prefetch_associations_on_fetched_records
|
18
|
-
Item.send(:cache_belongs_to, :item)
|
19
|
-
john = Item.create!(:title => 'john')
|
20
|
-
jim = Item.create!(:title => 'jim')
|
21
|
-
@bob.update_column(:item_id, john.id)
|
22
|
-
@joe.update_column(:item_id, jim.id)
|
23
|
-
items = Item.fetch_multi(@bob.id, @joe.id, @fred.id)
|
24
|
-
|
25
|
-
spy = Spy.on(Item, :fetch_multi).and_call_through
|
26
|
-
|
27
|
-
Item.prefetch_associations(:item, items)
|
28
|
-
|
29
|
-
assert spy.calls.one?{ |call| call.args == [[john.id, jim.id]] }
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_prefetch_associations_on_db_records
|
33
|
-
Item.send(:cache_has_many, :associated_records, :embed => true)
|
34
|
-
AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
|
35
|
-
|
36
|
-
setup_has_many_children_and_grandchildren(@bob)
|
37
|
-
|
38
|
-
item = Item.find(@bob.id)
|
39
|
-
|
40
|
-
assert_no_queries do
|
41
|
-
assert_memcache_operations(1) do
|
42
|
-
Item.prefetch_associations(:associated_records, [item])
|
43
|
-
end
|
44
|
-
assert_memcache_operations(0) do
|
45
|
-
item.fetch_associated_records.each(&:fetch_deeply_associated_record_ids)
|
46
|
-
end
|
47
|
-
assert_memcache_operations(1) do
|
48
|
-
Item.prefetch_associations({associated_records: :deeply_associated_records}, [item])
|
49
|
-
end
|
50
|
-
assert_memcache_operations(0) do
|
51
|
-
item.fetch_associated_records.each(&:fetch_deeply_associated_records)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def test_prefetch_associations_without_using_cache
|
57
|
-
Item.send(:cache_has_many, :associated_records, :embed => true)
|
58
|
-
|
59
|
-
associated1 = @bob.associated_records.create!(name: 'foo')
|
60
|
-
associated2 = @joe.associated_records.create!(name: 'bar')
|
61
|
-
items = [@bob, @joe].map(&:reload)
|
62
|
-
|
63
|
-
Item.transaction do
|
64
|
-
assert_memcache_operations(0) do
|
65
|
-
assert_queries(1) do
|
66
|
-
Item.prefetch_associations(:associated_records, items)
|
67
|
-
end
|
68
|
-
assert_no_queries do
|
69
|
-
assert_equal [[associated1], [associated2]], items.map(&:fetch_associated_records)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_prefetch_associations_cached_belongs_to
|
76
|
-
Item.send(:cache_belongs_to, :item)
|
77
|
-
@bob.update_attributes!(item_id: @joe.id)
|
78
|
-
@joe.update_attributes!(item_id: @fred.id)
|
79
|
-
@bob.fetch_item
|
80
|
-
@joe.fetch_item
|
81
|
-
items = [@bob, @joe].map(&:reload)
|
82
|
-
|
83
|
-
assert_no_queries do
|
84
|
-
assert_memcache_operations(1) do
|
85
|
-
Item.prefetch_associations(:item, items)
|
86
|
-
end
|
87
|
-
assert_memcache_operations(0) do
|
88
|
-
items.each { |item| item.fetch_item }
|
89
|
-
end
|
90
|
-
assert_memcache_operations(0) do
|
91
|
-
Item.prefetch_associations(:item, items)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_prefetch_associations_with_nil_cached_belongs_to
|
97
|
-
Item.send(:cache_belongs_to, :item)
|
98
|
-
@bob.update_attributes!(item_id: 1234)
|
99
|
-
assert_nil @bob.fetch_item
|
100
|
-
|
101
|
-
assert_no_queries do
|
102
|
-
assert_memcache_operations(0) do
|
103
|
-
Item.prefetch_associations(:item, [@bob])
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_prefetch_associations_on_association
|
109
|
-
AssociatedRecord.send(:cache_has_many, :deeply_associated_records, embed: true)
|
110
|
-
|
111
|
-
setup_has_many_children_and_grandchildren(@bob)
|
112
|
-
|
113
|
-
associated_records = @bob.associated_records
|
114
|
-
|
115
|
-
assert_queries(1) do
|
116
|
-
assert_memcache_operations(1) do
|
117
|
-
AssociatedRecord.prefetch_associations(:deeply_associated_records, associated_records)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
assert_no_queries do
|
121
|
-
assert_memcache_operations(0) do
|
122
|
-
associated_records.each(&:fetch_deeply_associated_records)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def test_fetch_with_includes_option
|
128
|
-
Item.send(:cache_belongs_to, :item)
|
129
|
-
john = Item.create!(title: 'john')
|
130
|
-
@bob.update_column(:item_id, john.id)
|
131
|
-
|
132
|
-
spy = Spy.on(Item, :fetch_multi).and_call_through
|
133
|
-
|
134
|
-
assert_equal @bob, Item.fetch(@bob.id, includes: :item)
|
135
|
-
|
136
|
-
assert spy.calls.one?{ |call| call.args == [[john.id]] }
|
137
|
-
end
|
138
|
-
|
139
|
-
def test_fetch_multi_with_includes_option
|
140
|
-
Item.send(:cache_belongs_to, :item)
|
141
|
-
john = Item.create!(:title => 'john')
|
142
|
-
jim = Item.create!(:title => 'jim')
|
143
|
-
@bob.update_column(:item_id, john.id)
|
144
|
-
@joe.update_column(:item_id, jim.id)
|
145
|
-
|
146
|
-
spy = Spy.on(Item, :fetch_multi).and_call_through
|
147
|
-
|
148
|
-
assert_equal [@bob, @joe, @fred], Item.fetch_multi(@bob.id, @joe.id, @fred.id, :includes => :item)
|
149
|
-
|
150
|
-
assert spy.calls.one?{ |call| call.args == [[john.id, jim.id]] }
|
151
|
-
end
|
152
|
-
|
153
|
-
def test_fetch_multi_batch_fetches_non_embedded_first_level_has_many_associations
|
154
|
-
Item.send(:cache_has_many, :associated_records, :embed => :ids)
|
155
|
-
|
156
|
-
child_records = []
|
157
|
-
[@bob, @joe].each do |parent|
|
158
|
-
3.times do |i|
|
159
|
-
child_records << (child_record = parent.associated_records.create!(:name => i.to_s))
|
160
|
-
AssociatedRecord.fetch(child_record.id)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
Item.fetch_multi(@bob.id, @joe.id) # populate the cache entries and associated children ID variables
|
165
|
-
|
166
|
-
assert_memcache_operations(2) do
|
167
|
-
@cached_bob, @cached_joe = Item.fetch_multi(@bob.id, @joe.id, :includes => :associated_records)
|
168
|
-
assert_equal child_records[0..2].sort, @cached_bob.fetch_associated_records.sort
|
169
|
-
assert_equal child_records[3..5].sort, @cached_joe.fetch_associated_records.sort
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def test_fetch_multi_batch_fetches_first_level_belongs_to_associations
|
174
|
-
AssociatedRecord.send(:cache_belongs_to, :item, :embed => false)
|
175
|
-
|
176
|
-
@bob_child = @bob.associated_records.create!(:name => "bob child")
|
177
|
-
@fred_child = @fred.associated_records.create!(:name => "fred child")
|
178
|
-
|
179
|
-
# populate the cache entries and associated children ID variables
|
180
|
-
AssociatedRecord.fetch_multi(@bob_child.id, @fred_child.id)
|
181
|
-
Item.fetch_multi(@bob.id, @fred.id)
|
182
|
-
|
183
|
-
assert_memcache_operations(2) do
|
184
|
-
@cached_bob_child, @cached_fred_child = AssociatedRecord.fetch_multi(@bob_child.id, @fred_child.id, :includes => :item)
|
185
|
-
assert_equal @bob, @cached_bob_child.fetch_item
|
186
|
-
assert_equal @fred, @cached_fred_child.fetch_item
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def test_fetch_multi_batch_fetches_first_level_associations_who_dont_include_identity_cache
|
191
|
-
NotCachedRecord.include(IdentityCache::WithoutPrimaryIndex)
|
192
|
-
Item.send(:cache_has_many, :not_cached_records, :embed => true)
|
193
|
-
|
194
|
-
@bob_child = @bob.not_cached_records.create!(:name => "bob child")
|
195
|
-
@fred_child = @fred.not_cached_records.create!(:name => "fred child")
|
196
|
-
|
197
|
-
# populate the cache entries and associated children ID variables
|
198
|
-
Item.fetch_multi(@bob.id, @fred.id)
|
199
|
-
|
200
|
-
assert_memcache_operations(1) do
|
201
|
-
@cached_bob_child, @cached_fred_child = Item.fetch_multi(@bob.id, @fred.id, :includes => :not_cached_records)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def test_fetch_multi_batch_fetches_non_embedded_second_level_has_many_associations
|
206
|
-
Item.send(:cache_has_many, :associated_records, :embed => :ids)
|
207
|
-
AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
|
208
|
-
|
209
|
-
_child_records, grandchildren = setup_has_many_children_and_grandchildren(@bob, @joe)
|
210
|
-
|
211
|
-
assert_memcache_operations(3) do
|
212
|
-
@cached_bob, @cached_joe = Item.fetch_multi(@bob.id, @joe.id, :includes => {:associated_records => :deeply_associated_records})
|
213
|
-
bob_children = @cached_bob.fetch_associated_records.sort
|
214
|
-
joe_children = @cached_joe.fetch_associated_records.sort
|
215
|
-
|
216
|
-
assert_equal grandchildren[0..2].sort, bob_children[0].fetch_deeply_associated_records.sort
|
217
|
-
assert_equal grandchildren[3..5].sort, bob_children[1].fetch_deeply_associated_records.sort
|
218
|
-
assert_equal grandchildren[6..8].sort, bob_children[2].fetch_deeply_associated_records.sort
|
219
|
-
assert_equal grandchildren[9..11].sort, joe_children[0].fetch_deeply_associated_records.sort
|
220
|
-
assert_equal grandchildren[12..14].sort, joe_children[1].fetch_deeply_associated_records.sort
|
221
|
-
assert_equal grandchildren[15..17].sort, joe_children[2].fetch_deeply_associated_records.sort
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def test_fetch_multi_batch_fetches_non_embedded_second_level_belongs_to_associations
|
226
|
-
Item.send(:cache_belongs_to, :item, :embed => false)
|
227
|
-
AssociatedRecord.send(:cache_belongs_to, :item, :embed => false)
|
228
|
-
|
229
|
-
@bob_child = @bob.associated_records.create!(:name => "bob child")
|
230
|
-
@fred_child = @fred.associated_records.create!(:name => "fred child")
|
231
|
-
@bob.update_attribute(:item_id, @bob.id)
|
232
|
-
@fred.update_attribute(:item_id, @fred.id)
|
233
|
-
|
234
|
-
# populate the cache entries and associated children ID variables
|
235
|
-
AssociatedRecord.fetch_multi(@bob_child.id, @fred_child.id)
|
236
|
-
Item.fetch_multi(@bob.id, @fred.id)
|
237
|
-
|
238
|
-
assert_memcache_operations(3) do
|
239
|
-
@cached_bob_child, @cached_fred_child = AssociatedRecord.fetch_multi(@bob_child.id, @fred_child.id, :includes => {:item => :item})
|
240
|
-
|
241
|
-
@cached_bob_parent = @cached_bob_child.fetch_item
|
242
|
-
@cached_fred_parent = @cached_fred_child.fetch_item
|
243
|
-
assert_equal @bob, @cached_bob_parent.fetch_item
|
244
|
-
assert_equal @fred, @cached_fred_parent.fetch_item
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def test_fetch_multi_doesnt_batch_fetches_belongs_to_associations_if_the_foreign_key_isnt_present
|
249
|
-
AssociatedRecord.send(:cache_belongs_to, :item, :embed => false)
|
250
|
-
@child = AssociatedRecord.create!(:name => "bob child")
|
251
|
-
# populate the cache entry
|
252
|
-
AssociatedRecord.fetch_multi(@child.id)
|
253
|
-
|
254
|
-
assert_memcache_operations(1) do
|
255
|
-
@cached_child = AssociatedRecord.fetch_multi(@child.id, :includes => :item)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
|
260
|
-
def test_fetch_multi_batch_fetches_non_embedded_second_level_associations_through_embedded_first_level_has_many_associations
|
261
|
-
Item.send(:cache_has_many, :associated_records, :embed => true)
|
262
|
-
AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
|
263
|
-
|
264
|
-
_child_records, grandchildren = setup_has_many_children_and_grandchildren(@bob, @joe)
|
265
|
-
|
266
|
-
assert_memcache_operations(2) do
|
267
|
-
@cached_bob, @cached_joe = Item.fetch_multi(@bob.id, @joe.id, :includes => {:associated_records => :deeply_associated_records})
|
268
|
-
bob_children = @cached_bob.fetch_associated_records.sort
|
269
|
-
joe_children = @cached_joe.fetch_associated_records.sort
|
270
|
-
|
271
|
-
assert_equal grandchildren[0..2].sort, bob_children[0].fetch_deeply_associated_records.sort
|
272
|
-
assert_equal grandchildren[3..5].sort, bob_children[1].fetch_deeply_associated_records.sort
|
273
|
-
assert_equal grandchildren[6..8].sort, bob_children[2].fetch_deeply_associated_records.sort
|
274
|
-
assert_equal grandchildren[9..11].sort, joe_children[0].fetch_deeply_associated_records.sort
|
275
|
-
assert_equal grandchildren[12..14].sort, joe_children[1].fetch_deeply_associated_records.sort
|
276
|
-
assert_equal grandchildren[15..17].sort, joe_children[2].fetch_deeply_associated_records.sort
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def test_fetch_multi_batch_fetches_non_embedded_second_level_associations_through_embedded_first_level_has_one_associations
|
281
|
-
Item.send(:cache_has_one, :associated, :embed => true)
|
282
|
-
AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
|
283
|
-
|
284
|
-
@bob_child = @bob.create_associated!(:name => "bob child")
|
285
|
-
@joe_child = @joe.create_associated!(:name => "joe child")
|
286
|
-
|
287
|
-
grandchildren = setup_grandchildren(@bob_child, @joe_child)
|
288
|
-
AssociatedRecord.fetch_multi(@bob_child.id, @joe_child.id)
|
289
|
-
Item.fetch_multi(@bob.id, @joe.id)
|
290
|
-
|
291
|
-
assert_memcache_operations(2) do
|
292
|
-
@cached_bob, @cached_joe = Item.fetch_multi(@bob.id, @joe.id, :includes => {:associated => :deeply_associated_records})
|
293
|
-
bob_child = @cached_bob.fetch_associated
|
294
|
-
joe_child = @cached_joe.fetch_associated
|
295
|
-
|
296
|
-
assert_equal grandchildren[0..2].sort, bob_child.fetch_deeply_associated_records.sort
|
297
|
-
assert_equal grandchildren[3..5].sort, joe_child.fetch_deeply_associated_records.sort
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
def test_find_batch_coerces_ids_to_primary_key_type
|
302
|
-
mock_relation = mock("ActiveRecord::Relation")
|
303
|
-
Item.expects(:where).returns(mock_relation)
|
304
|
-
mock_relation.expects(:includes).returns(stub(:to_a => [@bob, @joe, @fred]))
|
305
|
-
|
306
|
-
Item.send(:find_batch, [@bob, @joe, @fred].map(&:id).map(&:to_s))
|
307
|
-
end
|
308
|
-
|
309
|
-
def test_fetch_by_index_with_includes_option
|
310
|
-
Item.send(:cache_belongs_to, :item)
|
311
|
-
Item.cache_index :title
|
312
|
-
john = Item.create!(title: 'john')
|
313
|
-
@bob.update_column(:item_id, john.id)
|
314
|
-
|
315
|
-
spy = Spy.on(Item, :fetch_multi).and_call_through
|
316
|
-
|
317
|
-
assert_equal [@bob], Item.fetch_by_title('bob', includes: :item)
|
318
|
-
|
319
|
-
assert spy.calls.one?{ |call| call.args == [[john.id]] }
|
320
|
-
end
|
321
|
-
|
322
|
-
def test_fetch_by_unique_index_with_includes_option
|
323
|
-
Item.send(:cache_belongs_to, :item)
|
324
|
-
Item.cache_index :title, :unique => true
|
325
|
-
john = Item.create!(title: 'john')
|
326
|
-
@bob.update_column(:item_id, john.id)
|
327
|
-
|
328
|
-
spy = Spy.on(Item, :fetch_multi).and_call_through
|
329
|
-
|
330
|
-
assert_equal @bob, Item.fetch_by_title('bob', includes: :item)
|
331
|
-
|
332
|
-
assert spy.calls.one?{ |call| call.args == [[john.id]] }
|
333
|
-
end
|
334
|
-
|
335
|
-
private
|
336
|
-
|
337
|
-
def setup_has_many_children_and_grandchildren(*parents)
|
338
|
-
child_records = []
|
339
|
-
grandchildren = []
|
340
|
-
|
341
|
-
parents.each do |parent|
|
342
|
-
3.times do |i|
|
343
|
-
child_records << (child = parent.associated_records.create!(:name => i.to_s))
|
344
|
-
grandchildren.concat setup_grandchildren(child)
|
345
|
-
AssociatedRecord.fetch(child.id)
|
346
|
-
end
|
347
|
-
end
|
348
|
-
|
349
|
-
Item.fetch_multi(*parents.map(&:id)) # populate the cache entries and associated children ID variables
|
350
|
-
|
351
|
-
return child_records, grandchildren
|
352
|
-
end
|
353
|
-
|
354
|
-
def setup_grandchildren(*children)
|
355
|
-
grandchildren = []
|
356
|
-
children.each do |child|
|
357
|
-
3.times do |j|
|
358
|
-
grandchildren << (grandchild = child.deeply_associated_records.create!(:name => j.to_s))
|
359
|
-
DeeplyAssociatedRecord.fetch(grandchild.id)
|
360
|
-
end
|
361
|
-
end
|
362
|
-
grandchildren
|
363
|
-
end
|
364
|
-
end
|
data/test/readonly_test.rb
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class ReadonlyTest < IdentityCache::TestCase
|
4
|
-
def setup
|
5
|
-
super
|
6
|
-
@key, @value = 'foo', 'bar'
|
7
|
-
@record = Item.new
|
8
|
-
@record.id = 1
|
9
|
-
@record.title = 'bob'
|
10
|
-
@bob = Item.create!(:title => 'bob')
|
11
|
-
@joe = Item.create!(:title => 'joe')
|
12
|
-
@fred = Item.create!(:title => 'fred')
|
13
|
-
IdentityCache.cache.clear
|
14
|
-
IdentityCache.readonly = true
|
15
|
-
end
|
16
|
-
|
17
|
-
def teardown
|
18
|
-
IdentityCache.readonly = nil
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_write_should_not_update_cache
|
23
|
-
assert_memcache_operations(0) do
|
24
|
-
fetcher.write(@key, @value)
|
25
|
-
end
|
26
|
-
assert_nil backend.read(@key)
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_delete_should_update_cache
|
30
|
-
backend.write(@key, @value)
|
31
|
-
fetcher.delete(@key)
|
32
|
-
assert_equal deleted_value, backend.read(@key)
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_clear_should_update_cache
|
36
|
-
backend.write(@key, @value)
|
37
|
-
fetcher.clear
|
38
|
-
assert_nil backend.read(@key)
|
39
|
-
end
|
40
|
-
|
41
|
-
def test_fetch_should_not_update_cache
|
42
|
-
fetch = Spy.on(IdentityCache.cache, :fetch).and_call_through
|
43
|
-
Item.expects(:resolve_cache_miss).with(1).once.returns(@record)
|
44
|
-
|
45
|
-
assert_readonly_fetch do
|
46
|
-
assert_equal @record, Item.fetch(1)
|
47
|
-
end
|
48
|
-
assert_nil backend.read(@record.primary_cache_index_key)
|
49
|
-
assert fetch.has_been_called_with?(@record.primary_cache_index_key)
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_fetch_multi_should_not_update_cache
|
53
|
-
fetch_multi = Spy.on(IdentityCache.cache, :fetch_multi).and_call_through
|
54
|
-
|
55
|
-
assert_readonly_fetch_multi do
|
56
|
-
assert_equal [@bob, @joe, @fred], Item.fetch_multi(@bob.id, @joe.id, @fred.id)
|
57
|
-
end
|
58
|
-
keys = [@bob, @joe, @fred].map(&:primary_cache_index_key)
|
59
|
-
assert_empty backend.read_multi(*keys)
|
60
|
-
assert fetch_multi.has_been_called_with?(*keys)
|
61
|
-
end
|
62
|
-
|
63
|
-
protected
|
64
|
-
|
65
|
-
def assert_readonly_fetch
|
66
|
-
cas = Spy.on(backend, :cas).and_call_through
|
67
|
-
yield
|
68
|
-
assert cas.has_been_called?
|
69
|
-
end
|
70
|
-
|
71
|
-
def assert_readonly_fetch_multi
|
72
|
-
cas_multi = Spy.on(backend, :cas_multi).and_call_through
|
73
|
-
yield
|
74
|
-
assert cas_multi.has_been_called?
|
75
|
-
end
|
76
|
-
|
77
|
-
def deleted_value
|
78
|
-
IdentityCache::DELETED
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
class FallbackReadonlyTest < ReadonlyTest
|
83
|
-
def setup
|
84
|
-
super
|
85
|
-
IdentityCache.cache_backend = @backend = ActiveSupport::Cache::MemoryStore.new
|
86
|
-
end
|
87
|
-
|
88
|
-
protected
|
89
|
-
|
90
|
-
def assert_readonly_fetch
|
91
|
-
read = Spy.on(backend, :read).and_call_through
|
92
|
-
write = Spy.on(backend, :write).and_call_through
|
93
|
-
yield
|
94
|
-
assert read.has_been_called?
|
95
|
-
refute write.has_been_called?
|
96
|
-
end
|
97
|
-
|
98
|
-
def assert_readonly_fetch_multi
|
99
|
-
read_multi = Spy.on(backend, :read_multi).and_call_through
|
100
|
-
write = Spy.on(backend, :write).and_call_through
|
101
|
-
yield
|
102
|
-
assert read_multi.has_been_called?
|
103
|
-
refute write.has_been_called?
|
104
|
-
end
|
105
|
-
|
106
|
-
def deleted_value
|
107
|
-
nil
|
108
|
-
end
|
109
|
-
end
|