identity_cache 0.0.7 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +3 -2
- data/CHANGELOG +13 -1
- data/Gemfile +2 -2
- data/{Gemfile.rails4 → Gemfile.rails41} +2 -2
- data/Gemfile32 +7 -0
- data/README.md +3 -4
- data/identity_cache.gemspec +3 -2
- data/lib/identity_cache/belongs_to_caching.rb +1 -1
- data/lib/identity_cache/cache_hash.rb +2 -2
- data/lib/identity_cache/cache_invalidation.rb +26 -0
- data/lib/identity_cache/cache_key_generation.rb +3 -2
- data/lib/identity_cache/configuration_dsl.rb +38 -32
- data/lib/identity_cache/query_api.rb +52 -52
- data/lib/identity_cache/version.rb +1 -1
- data/lib/identity_cache.rb +20 -8
- data/performance/cache_runner.rb +7 -4
- data/performance/profile.rb +13 -3
- data/test/attribute_cache_test.rb +13 -4
- data/test/cache_fetch_includes_test.rb +1 -44
- data/test/cache_invalidation_test.rb +52 -0
- data/test/denormalized_has_many_test.rb +4 -4
- data/test/fetch_multi_test.rb +54 -0
- data/test/fetch_multi_with_batched_associations_test.rb +13 -35
- data/test/fetch_test.rb +20 -6
- data/test/fixtures/serialized_record +0 -0
- data/test/helpers/active_record_objects.rb +8 -2
- data/test/helpers/database_connection.rb +8 -5
- data/test/helpers/serialization_format.rb +9 -5
- data/test/helpers/update_serialization_format.rb +1 -0
- data/test/index_cache_test.rb +21 -1
- data/test/memoized_cache_proxy_test.rb +9 -17
- data/test/normalized_belongs_to_test.rb +2 -0
- data/test/normalized_has_many_test.rb +4 -4
- data/test/recursive_denormalized_has_many_test.rb +1 -1
- data/test/schema_change_test.rb +2 -2
- data/test/test_helper.rb +7 -3
- metadata +26 -17
- data/test/helpers/cache.rb +0 -15
data/test/index_cache_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
class
|
3
|
+
class IndexCacheTest < IdentityCache::TestCase
|
4
4
|
NAMESPACE = IdentityCache::CacheKeyGeneration::DEFAULT_NAMESPACE
|
5
5
|
|
6
6
|
def setup
|
@@ -11,6 +11,26 @@ class ExpirationTest < IdentityCache::TestCase
|
|
11
11
|
@cache_key = "#{NAMESPACE}index:Item:title:#{cache_hash(@record.title)}"
|
12
12
|
end
|
13
13
|
|
14
|
+
def test_fetch_with_garbage_input_should_use_properly_typed_sql
|
15
|
+
Item.cache_index :title, :id
|
16
|
+
|
17
|
+
Item.connection.expects(:exec_query)
|
18
|
+
.with(regexp_matches(/ WHERE `items`\.`title` = 'garbage' AND `items`\.`id` = 0\z/i), anything)
|
19
|
+
.returns(ActiveRecord::Result.new([], []))
|
20
|
+
|
21
|
+
assert_equal [], Item.fetch_by_title_and_id('garbage', 'garbage')
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_fetch_with_unique_adds_limit_clause
|
25
|
+
Item.cache_index :title, :id, :unique => true
|
26
|
+
|
27
|
+
Item.connection.expects(:exec_query)
|
28
|
+
.with(regexp_matches(/ LIMIT 1\Z/i), anything)
|
29
|
+
.returns(ActiveRecord::Result.new([], []))
|
30
|
+
|
31
|
+
assert_equal nil, Item.fetch_by_title_and_id('title', '2')
|
32
|
+
end
|
33
|
+
|
14
34
|
def test_unique_index_caches_nil
|
15
35
|
Item.cache_index :title, :unique => true
|
16
36
|
assert_equal nil, Item.fetch_by_title('bob')
|
@@ -3,7 +3,7 @@ require "test_helper"
|
|
3
3
|
class MemoizedCacheProxyTest < IdentityCache::TestCase
|
4
4
|
def setup
|
5
5
|
super
|
6
|
-
|
6
|
+
@backend = IdentityCache.cache.cache_backend
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_changing_default_cache
|
@@ -13,7 +13,7 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_read_should_short_circuit_on_memoized_values
|
16
|
-
|
16
|
+
@backend.expects(:read).never
|
17
17
|
|
18
18
|
IdentityCache.cache.with_memoization do
|
19
19
|
IdentityCache.cache.write('foo', 'bar')
|
@@ -22,7 +22,7 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_read_should_short_circuit_on_falsy_memoized_values
|
25
|
-
|
25
|
+
@backend.expects(:read).never
|
26
26
|
|
27
27
|
IdentityCache.cache.with_memoization do
|
28
28
|
IdentityCache.cache.write('foo', nil)
|
@@ -33,7 +33,7 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_read_should_try_memcached_on_not_memoized_values
|
36
|
-
|
36
|
+
@backend.expects(:read).with('foo').returns('bar')
|
37
37
|
|
38
38
|
IdentityCache.cache.with_memoization do
|
39
39
|
assert_equal 'bar', IdentityCache.cache.read('foo')
|
@@ -41,9 +41,8 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def test_write_should_memoize_values
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
@backend.expects(:read).never
|
45
|
+
@backend.expects(:write).with('foo', 'bar')
|
47
46
|
|
48
47
|
IdentityCache.cache.with_memoization do
|
49
48
|
IdentityCache.cache.write('foo', 'bar')
|
@@ -76,7 +75,7 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
76
75
|
|
77
76
|
def test_read_multi_with_partially_memoized_should_read_missing_keys_from_memcache
|
78
77
|
IdentityCache.cache.write('foo', 'bar')
|
79
|
-
|
78
|
+
@backend.write('fooz', 'baz')
|
80
79
|
|
81
80
|
IdentityCache.cache.with_memoization do
|
82
81
|
assert_equal({'foo' => 'bar', 'fooz' => 'baz'}, IdentityCache.cache.read_multi('foo', 'fooz'))
|
@@ -84,7 +83,7 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
84
83
|
end
|
85
84
|
|
86
85
|
def test_read_multi_with_blank_values_should_not_hit_the_cache_engine
|
87
|
-
|
86
|
+
@backend.expects(:read_multi).never
|
88
87
|
|
89
88
|
IdentityCache.cache.with_memoization do
|
90
89
|
IdentityCache.cache.write('foo', [])
|
@@ -98,13 +97,6 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
98
97
|
IdentityCache.cache.with_memoization do
|
99
98
|
IdentityCache.cache.write('foo', 'bar')
|
100
99
|
end
|
101
|
-
|
102
|
-
assert_equal 'bar', Rails.cache.read('foo')
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_set_backend_should_not_touch_rails
|
106
|
-
Rails.expects(:cache).never
|
107
|
-
IdentityCache.instance_variable_set(:@cache, nil)
|
108
|
-
IdentityCache.cache_backend = Rails::Cache.new
|
100
|
+
assert_equal 'bar', @backend.read('foo')
|
109
101
|
end
|
110
102
|
end
|
@@ -10,6 +10,8 @@ class NormalizedBelongsToTest < IdentityCache::TestCase
|
|
10
10
|
@parent_record.save
|
11
11
|
@parent_record.reload
|
12
12
|
@record = @parent_record.associated_records.first
|
13
|
+
# Reset association cache, so we remove the inverse of in memory reference
|
14
|
+
@record.association(:item).reset
|
13
15
|
end
|
14
16
|
|
15
17
|
def test_fetching_the_association_should_delegate_to_the_normal_association_fetcher_if_any_transactions_are_open
|
@@ -3,7 +3,7 @@ require "test_helper"
|
|
3
3
|
class NormalizedHasManyTest < IdentityCache::TestCase
|
4
4
|
def setup
|
5
5
|
super
|
6
|
-
Item.cache_has_many :associated_records, :embed =>
|
6
|
+
Item.cache_has_many :associated_records, :embed => :ids
|
7
7
|
|
8
8
|
@record = Item.new(:title => 'foo')
|
9
9
|
@record.not_cached_records << NotCachedRecord.new(:name => 'NoCache')
|
@@ -99,7 +99,7 @@ class NormalizedHasManyTest < IdentityCache::TestCase
|
|
99
99
|
|
100
100
|
def test_saving_a_child_record_should_expire_the_new_and_old_parents_cache_blob
|
101
101
|
@new_record = Item.create
|
102
|
-
@baz.
|
102
|
+
@baz.item = @new_record
|
103
103
|
|
104
104
|
IdentityCache.cache.expects(:delete).with(@record.primary_cache_index_key).once
|
105
105
|
IdentityCache.cache.expects(:delete).with(@new_record.primary_cache_index_key).once
|
@@ -135,9 +135,9 @@ class NormalizedHasManyTest < IdentityCache::TestCase
|
|
135
135
|
assert_equal [@bar], @record.reload.fetch_associated_records
|
136
136
|
end
|
137
137
|
|
138
|
-
def
|
138
|
+
def test_saving_a_child_record_should_expire_only_itself
|
139
139
|
IdentityCache.cache.expects(:delete).with(@baz.primary_cache_index_key).once
|
140
|
-
@baz.
|
140
|
+
@baz.save!
|
141
141
|
end
|
142
142
|
|
143
143
|
def test_touching_child_with_touch_true_on_parent_expires_parent
|
@@ -94,7 +94,7 @@ class RecursiveNormalizedHasManyTest < IdentityCache::TestCase
|
|
94
94
|
def setup
|
95
95
|
super
|
96
96
|
AssociatedRecord.cache_has_many :deeply_associated_records, :embed => true
|
97
|
-
Item.cache_has_many :associated_records, :embed =>
|
97
|
+
Item.cache_has_many :associated_records, :embed => :ids
|
98
98
|
|
99
99
|
@record = Item.new(:title => 'foo')
|
100
100
|
@record.save
|
data/test/schema_change_test.rb
CHANGED
@@ -83,7 +83,7 @@ class SchemaChangeTest < IdentityCache::TestCase
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def test_embed_existing_cache_has_many
|
86
|
-
Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed =>
|
86
|
+
Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => :ids
|
87
87
|
read_new_schema
|
88
88
|
|
89
89
|
record = Item.fetch(@record.id)
|
@@ -98,7 +98,7 @@ class SchemaChangeTest < IdentityCache::TestCase
|
|
98
98
|
def test_add_non_embedded_cache_has_many
|
99
99
|
record = Item.fetch(@record.id)
|
100
100
|
|
101
|
-
Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed =>
|
101
|
+
Item.cache_has_many :polymorphic_records, :inverse_name => :owner, :embed => :ids
|
102
102
|
read_new_schema
|
103
103
|
|
104
104
|
Item.expects(:resolve_cache_miss).returns(@record)
|
data/test/test_helper.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
+
require 'logger'
|
1
2
|
require 'minitest/autorun'
|
2
3
|
require 'mocha/setup'
|
3
4
|
require 'active_record'
|
4
|
-
require 'memcached_store'
|
5
|
-
require 'active_support/cache/memcached_store'
|
6
|
-
require 'helpers/cache'
|
7
5
|
require 'helpers/database_connection'
|
8
6
|
require 'helpers/active_record_objects'
|
7
|
+
require 'spy'
|
8
|
+
require 'memcached_store'
|
9
|
+
require 'active_support/cache/memcached_store'
|
9
10
|
|
10
11
|
require File.dirname(__FILE__) + '/../lib/identity_cache'
|
11
12
|
|
@@ -38,6 +39,9 @@ class IdentityCache::TestCase < MiniTest::Unit::TestCase
|
|
38
39
|
DatabaseConnection.drop_tables
|
39
40
|
DatabaseConnection.create_tables
|
40
41
|
|
42
|
+
IdentityCache.logger = Logger.new(nil)
|
43
|
+
IdentityCache.cache_backend = ActiveSupport::Cache::MemcachedStore.new("localhost:#{$memcached_port}")
|
44
|
+
|
41
45
|
setup_models
|
42
46
|
end
|
43
47
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: identity_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Camilo Lopez
|
@@ -13,22 +13,22 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2014-
|
16
|
+
date: 2014-05-08 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: ar_transaction_changes
|
20
20
|
requirement: !ruby/object:Gem::Requirement
|
21
21
|
requirements:
|
22
|
-
- -
|
22
|
+
- - "~>"
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version:
|
24
|
+
version: '1.0'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
28
28
|
requirements:
|
29
|
-
- -
|
29
|
+
- - "~>"
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
version:
|
31
|
+
version: '1.0'
|
32
32
|
- !ruby/object:Gem::Dependency
|
33
33
|
name: activerecord
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
@@ -36,9 +36,6 @@ dependencies:
|
|
36
36
|
- - ">="
|
37
37
|
- !ruby/object:Gem::Version
|
38
38
|
version: '3.2'
|
39
|
-
- - "<"
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
version: '4.1'
|
42
39
|
type: :runtime
|
43
40
|
prerelease: false
|
44
41
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -46,9 +43,6 @@ dependencies:
|
|
46
43
|
- - ">="
|
47
44
|
- !ruby/object:Gem::Version
|
48
45
|
version: '3.2'
|
49
|
-
- - "<"
|
50
|
-
- !ruby/object:Gem::Version
|
51
|
-
version: '4.1'
|
52
46
|
- !ruby/object:Gem::Dependency
|
53
47
|
name: memcached_store
|
54
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -91,6 +85,20 @@ dependencies:
|
|
91
85
|
- - '='
|
92
86
|
- !ruby/object:Gem::Version
|
93
87
|
version: 0.14.0
|
88
|
+
- !ruby/object:Gem::Dependency
|
89
|
+
name: spy
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
type: :development
|
96
|
+
prerelease: false
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
94
102
|
- !ruby/object:Gem::Dependency
|
95
103
|
name: cityhash
|
96
104
|
requirement: !ruby/object:Gem::Requirement
|
@@ -145,7 +153,8 @@ files:
|
|
145
153
|
- ".travis.yml"
|
146
154
|
- CHANGELOG
|
147
155
|
- Gemfile
|
148
|
-
- Gemfile.
|
156
|
+
- Gemfile.rails41
|
157
|
+
- Gemfile32
|
149
158
|
- LICENSE
|
150
159
|
- README.md
|
151
160
|
- Rakefile
|
@@ -153,6 +162,7 @@ files:
|
|
153
162
|
- lib/identity_cache.rb
|
154
163
|
- lib/identity_cache/belongs_to_caching.rb
|
155
164
|
- lib/identity_cache/cache_hash.rb
|
165
|
+
- lib/identity_cache/cache_invalidation.rb
|
156
166
|
- lib/identity_cache/cache_key_generation.rb
|
157
167
|
- lib/identity_cache/configuration_dsl.rb
|
158
168
|
- lib/identity_cache/memoized_cache_proxy.rb
|
@@ -166,6 +176,7 @@ files:
|
|
166
176
|
- test/attribute_cache_test.rb
|
167
177
|
- test/cache_fetch_includes_test.rb
|
168
178
|
- test/cache_hash_test.rb
|
179
|
+
- test/cache_invalidation_test.rb
|
169
180
|
- test/denormalized_has_many_test.rb
|
170
181
|
- test/denormalized_has_one_test.rb
|
171
182
|
- test/fetch_multi_test.rb
|
@@ -173,7 +184,6 @@ files:
|
|
173
184
|
- test/fetch_test.rb
|
174
185
|
- test/fixtures/serialized_record
|
175
186
|
- test/helpers/active_record_objects.rb
|
176
|
-
- test/helpers/cache.rb
|
177
187
|
- test/helpers/database_connection.rb
|
178
188
|
- test/helpers/serialization_format.rb
|
179
189
|
- test/helpers/update_serialization_format.rb
|
@@ -207,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
217
|
version: '0'
|
208
218
|
requirements: []
|
209
219
|
rubyforge_project:
|
210
|
-
rubygems_version: 2.2.
|
220
|
+
rubygems_version: 2.2.2
|
211
221
|
signing_key:
|
212
222
|
specification_version: 4
|
213
223
|
summary: IdentityCache lets you specify how you want to cache your model objects,
|
@@ -218,6 +228,7 @@ test_files:
|
|
218
228
|
- test/attribute_cache_test.rb
|
219
229
|
- test/cache_fetch_includes_test.rb
|
220
230
|
- test/cache_hash_test.rb
|
231
|
+
- test/cache_invalidation_test.rb
|
221
232
|
- test/denormalized_has_many_test.rb
|
222
233
|
- test/denormalized_has_one_test.rb
|
223
234
|
- test/fetch_multi_test.rb
|
@@ -225,7 +236,6 @@ test_files:
|
|
225
236
|
- test/fetch_test.rb
|
226
237
|
- test/fixtures/serialized_record
|
227
238
|
- test/helpers/active_record_objects.rb
|
228
|
-
- test/helpers/cache.rb
|
229
239
|
- test/helpers/database_connection.rb
|
230
240
|
- test/helpers/serialization_format.rb
|
231
241
|
- test/helpers/update_serialization_format.rb
|
@@ -240,4 +250,3 @@ test_files:
|
|
240
250
|
- test/schema_change_test.rb
|
241
251
|
- test/serialization_format_change_test.rb
|
242
252
|
- test/test_helper.rb
|
243
|
-
has_rdoc:
|
data/test/helpers/cache.rb
DELETED