identity_cache 0.3.1 → 0.3.2
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 +4 -4
- data/.travis.yml +8 -2
- data/CHANGELOG.md +8 -0
- data/Gemfile.rails50 +6 -0
- data/README.md +10 -0
- data/dev.yml +54 -0
- data/identity_cache.gemspec +4 -4
- data/lib/identity_cache/belongs_to_caching.rb +5 -1
- data/lib/identity_cache/cache_key_generation.rb +1 -0
- data/lib/identity_cache/configuration_dsl.rb +13 -12
- data/lib/identity_cache/parent_model_expiration.rb +1 -1
- data/lib/identity_cache/query_api.rb +174 -82
- data/lib/identity_cache/version.rb +1 -1
- data/lib/identity_cache.rb +45 -1
- data/performance/cache_runner.rb +1 -1
- data/test/cache_hash_test.rb +0 -2
- data/test/cache_invalidation_test.rb +5 -4
- data/test/denormalized_has_many_test.rb +101 -7
- data/test/denormalized_has_one_test.rb +36 -0
- data/test/fetch_multi_test.rb +42 -0
- data/test/fetch_test.rb +32 -0
- data/test/helpers/database_connection.rb +4 -3
- data/test/index_cache_test.rb +2 -2
- data/test/memoized_attributes_test.rb +49 -0
- data/test/normalized_belongs_to_test.rb +24 -0
- data/test/normalized_has_many_test.rb +29 -5
- data/test/{prefetch_normalized_associations_test.rb → prefetch_associations_test.rb} +118 -9
- data/test/recursive_denormalized_has_many_test.rb +18 -2
- data/test/schema_change_test.rb +3 -2
- data/test/test_helper.rb +4 -2
- metadata +13 -12
- data/.ruby-version +0 -1
- data/Gemfile.rails40 +0 -6
- data/Gemfile.rails41 +0 -6
@@ -1,6 +1,6 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
class
|
3
|
+
class PrefetchAssociationsTest < IdentityCache::TestCase
|
4
4
|
NAMESPACE = IdentityCache.cache_namespace
|
5
5
|
|
6
6
|
def setup
|
@@ -14,10 +14,120 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
|
|
14
14
|
@tenth_blob_key = "#{NAMESPACE}blob:Item:#{cache_hash("created_at:datetime,id:integer,item_id:integer,title:string,updated_at:datetime")}:10"
|
15
15
|
end
|
16
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_equal 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
|
+
|
17
127
|
def test_fetch_with_includes_option
|
18
128
|
Item.send(:cache_belongs_to, :item)
|
19
129
|
john = Item.create!(title: 'john')
|
20
|
-
@bob.update_column(:item_id, john)
|
130
|
+
@bob.update_column(:item_id, john.id)
|
21
131
|
|
22
132
|
spy = Spy.on(Item, :fetch_multi).and_call_through
|
23
133
|
|
@@ -30,8 +140,8 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
|
|
30
140
|
Item.send(:cache_belongs_to, :item)
|
31
141
|
john = Item.create!(:title => 'john')
|
32
142
|
jim = Item.create!(:title => 'jim')
|
33
|
-
@bob.update_column(:item_id, john)
|
34
|
-
@joe.update_column(:item_id, jim)
|
143
|
+
@bob.update_column(:item_id, john.id)
|
144
|
+
@joe.update_column(:item_id, jim.id)
|
35
145
|
|
36
146
|
spy = Spy.on(Item, :fetch_multi).and_call_through
|
37
147
|
|
@@ -78,7 +188,6 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
|
|
78
188
|
end
|
79
189
|
|
80
190
|
def test_fetch_multi_batch_fetches_first_level_associations_who_dont_include_identity_cache
|
81
|
-
Item.send(:has_many, :not_cached_records)
|
82
191
|
Item.send(:cache_has_many, :not_cached_records, :embed => true)
|
83
192
|
|
84
193
|
@bob_child = @bob.not_cached_records.create!(:name => "bob child")
|
@@ -96,7 +205,7 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
|
|
96
205
|
Item.send(:cache_has_many, :associated_records, :embed => :ids)
|
97
206
|
AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
|
98
207
|
|
99
|
-
|
208
|
+
_child_records, grandchildren = setup_has_many_children_and_grandchildren(@bob, @joe)
|
100
209
|
|
101
210
|
assert_memcache_operations(3) do
|
102
211
|
@cached_bob, @cached_joe = Item.fetch_multi(@bob.id, @joe.id, :includes => {:associated_records => :deeply_associated_records})
|
@@ -151,7 +260,7 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
|
|
151
260
|
Item.send(:cache_has_many, :associated_records, :embed => true)
|
152
261
|
AssociatedRecord.send(:cache_has_many, :deeply_associated_records, :embed => :ids)
|
153
262
|
|
154
|
-
|
263
|
+
_child_records, grandchildren = setup_has_many_children_and_grandchildren(@bob, @joe)
|
155
264
|
|
156
265
|
assert_memcache_operations(2) do
|
157
266
|
@cached_bob, @cached_joe = Item.fetch_multi(@bob.id, @joe.id, :includes => {:associated_records => :deeply_associated_records})
|
@@ -200,7 +309,7 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
|
|
200
309
|
Item.send(:cache_belongs_to, :item)
|
201
310
|
Item.cache_index :title
|
202
311
|
john = Item.create!(title: 'john')
|
203
|
-
@bob.update_column(:item_id, john)
|
312
|
+
@bob.update_column(:item_id, john.id)
|
204
313
|
|
205
314
|
spy = Spy.on(Item, :fetch_multi).and_call_through
|
206
315
|
|
@@ -213,7 +322,7 @@ class PrefetchNormalizedAssociationsTest < IdentityCache::TestCase
|
|
213
322
|
Item.send(:cache_belongs_to, :item)
|
214
323
|
Item.cache_index :title, :unique => true
|
215
324
|
john = Item.create!(title: 'john')
|
216
|
-
@bob.update_column(:item_id, john)
|
325
|
+
@bob.update_column(:item_id, john.id)
|
217
326
|
|
218
327
|
spy = Spy.on(Item, :fetch_multi).and_call_through
|
219
328
|
|
@@ -61,7 +61,7 @@ class RecursiveDenormalizedHasManyTest < IdentityCache::TestCase
|
|
61
61
|
# one for the mid level has_one association
|
62
62
|
# one for the deep level level has_many on the mid level has_many association
|
63
63
|
# one for the deep level level has_many on the mid level has_one association
|
64
|
-
|
64
|
+
Item.fetch(@record.id)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
@@ -88,6 +88,22 @@ class RecursiveDenormalizedHasManyTest < IdentityCache::TestCase
|
|
88
88
|
@deeply_associated_record.save!
|
89
89
|
end
|
90
90
|
|
91
|
+
def test_set_inverse_associations
|
92
|
+
DeeplyAssociatedRecord.cache_belongs_to :associated_record
|
93
|
+
AssociatedRecord.cache_belongs_to :item
|
94
|
+
Item.fetch(@record.id) # warm cache
|
95
|
+
|
96
|
+
item = Item.fetch(@record.id)
|
97
|
+
|
98
|
+
assert_queries(0) do
|
99
|
+
assert_memcache_operations(0) do
|
100
|
+
associated_record = item.fetch_associated_records.to_a.first
|
101
|
+
deeply_associated_record = associated_record.fetch_deeply_associated_records.first
|
102
|
+
assert_equal item.id, deeply_associated_record.fetch_associated_record.fetch_item.id
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
91
107
|
end
|
92
108
|
|
93
109
|
class RecursiveNormalizedHasManyTest < IdentityCache::TestCase
|
@@ -103,7 +119,7 @@ class RecursiveNormalizedHasManyTest < IdentityCache::TestCase
|
|
103
119
|
|
104
120
|
def test_cache_repopulation_should_not_fetch_non_embedded_associations
|
105
121
|
Item.any_instance.expects(:fetch_associated_records).never
|
106
|
-
|
122
|
+
Item.fetch(@record.id) # cache miss
|
107
123
|
end
|
108
124
|
end
|
109
125
|
|
data/test/schema_change_test.rb
CHANGED
@@ -89,10 +89,12 @@ class SchemaChangeTest < IdentityCache::TestCase
|
|
89
89
|
|
90
90
|
record = Item.fetch(@record.id)
|
91
91
|
|
92
|
+
teardown_models
|
93
|
+
setup_models
|
94
|
+
|
92
95
|
Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => true
|
93
96
|
read_new_schema
|
94
97
|
|
95
|
-
Item.expects(:resolve_cache_miss).returns(@record)
|
96
98
|
record = Item.fetch(@record.id)
|
97
99
|
end
|
98
100
|
|
@@ -103,7 +105,6 @@ class SchemaChangeTest < IdentityCache::TestCase
|
|
103
105
|
Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => :ids
|
104
106
|
read_new_schema
|
105
107
|
|
106
|
-
Item.expects(:resolve_cache_miss).returns(@record)
|
107
108
|
record = Item.fetch(@record.id)
|
108
109
|
end
|
109
110
|
end
|
data/test/test_helper.rb
CHANGED
@@ -11,7 +11,7 @@ require 'active_support/cache/memcached_store'
|
|
11
11
|
require File.dirname(__FILE__) + '/../lib/identity_cache'
|
12
12
|
|
13
13
|
DatabaseConnection.setup
|
14
|
-
ActiveSupport::Cache::Store.instrument = true
|
14
|
+
ActiveSupport::Cache::Store.instrument = true if ActiveSupport.version < Gem::Version.new("4.2.0")
|
15
15
|
|
16
16
|
# This patches AR::MemcacheStore to notify AS::Notifications upon read_multis like the rest of rails does
|
17
17
|
class ActiveSupport::Cache::MemcachedStore
|
@@ -38,7 +38,9 @@ class IdentityCache::TestCase < Minitest::Test
|
|
38
38
|
DatabaseConnection.create_tables
|
39
39
|
|
40
40
|
IdentityCache.logger = Logger.new(nil)
|
41
|
-
|
41
|
+
|
42
|
+
memcached_host = ENV['MEMCACHED_HOST'] || "127.0.0.1"
|
43
|
+
IdentityCache.cache_backend = @backend = ActiveSupport::Cache::MemcachedStore.new("#{memcached_host}:11211", :support_cas => true)
|
42
44
|
|
43
45
|
setup_models
|
44
46
|
end
|
metadata
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: identity_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Camilo Lopez
|
8
8
|
- Tom Burns
|
9
9
|
- Harry Brundage
|
10
|
-
- Dylan Smith
|
10
|
+
- Dylan Thacker-Smith
|
11
11
|
- Tobias Lutke
|
12
12
|
- Arthur Neves
|
13
13
|
- Francis Bogsanyi
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2016-
|
17
|
+
date: 2016-08-10 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: ar_transaction_changes
|
@@ -36,14 +36,14 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 4.0
|
39
|
+
version: 4.2.0
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 4.0
|
46
|
+
version: 4.2.0
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: memcached
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -186,23 +186,22 @@ dependencies:
|
|
186
186
|
version: '0'
|
187
187
|
description: Opt in read through ActiveRecord caching.
|
188
188
|
email:
|
189
|
-
-
|
189
|
+
- gems@shopify.com
|
190
190
|
executables: []
|
191
191
|
extensions: []
|
192
192
|
extra_rdoc_files: []
|
193
193
|
files:
|
194
194
|
- ".gitignore"
|
195
|
-
- ".ruby-version"
|
196
195
|
- ".travis.yml"
|
197
196
|
- CHANGELOG.md
|
198
197
|
- CONTRIBUTING.md
|
199
198
|
- Gemfile
|
200
|
-
- Gemfile.rails40
|
201
|
-
- Gemfile.rails41
|
202
199
|
- Gemfile.rails42
|
200
|
+
- Gemfile.rails50
|
203
201
|
- LICENSE
|
204
202
|
- README.md
|
205
203
|
- Rakefile
|
204
|
+
- dev.yml
|
206
205
|
- identity_cache.gemspec
|
207
206
|
- lib/identity_cache.rb
|
208
207
|
- lib/identity_cache/belongs_to_caching.rb
|
@@ -238,11 +237,12 @@ files:
|
|
238
237
|
- test/helpers/update_serialization_format.rb
|
239
238
|
- test/identity_cache_test.rb
|
240
239
|
- test/index_cache_test.rb
|
240
|
+
- test/memoized_attributes_test.rb
|
241
241
|
- test/memoized_cache_proxy_test.rb
|
242
242
|
- test/normalized_belongs_to_test.rb
|
243
243
|
- test/normalized_has_many_test.rb
|
244
244
|
- test/normalized_has_one_test.rb
|
245
|
-
- test/
|
245
|
+
- test/prefetch_associations_test.rb
|
246
246
|
- test/readonly_test.rb
|
247
247
|
- test/recursive_denormalized_has_many_test.rb
|
248
248
|
- test/save_test.rb
|
@@ -268,7 +268,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
268
268
|
version: '0'
|
269
269
|
requirements: []
|
270
270
|
rubyforge_project:
|
271
|
-
rubygems_version: 2.
|
271
|
+
rubygems_version: 2.5.1
|
272
272
|
signing_key:
|
273
273
|
specification_version: 4
|
274
274
|
summary: IdentityCache lets you specify how you want to cache your model objects,
|
@@ -293,11 +293,12 @@ test_files:
|
|
293
293
|
- test/helpers/update_serialization_format.rb
|
294
294
|
- test/identity_cache_test.rb
|
295
295
|
- test/index_cache_test.rb
|
296
|
+
- test/memoized_attributes_test.rb
|
296
297
|
- test/memoized_cache_proxy_test.rb
|
297
298
|
- test/normalized_belongs_to_test.rb
|
298
299
|
- test/normalized_has_many_test.rb
|
299
300
|
- test/normalized_has_one_test.rb
|
300
|
-
- test/
|
301
|
+
- test/prefetch_associations_test.rb
|
301
302
|
- test/readonly_test.rb
|
302
303
|
- test/recursive_denormalized_has_many_test.rb
|
303
304
|
- test/save_test.rb
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.2.2
|
data/Gemfile.rails40
DELETED