identity_cache 0.0.2 → 0.0.3
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 +7 -0
- data/.travis.yml +1 -0
- data/CHANGELOG +7 -0
- data/README.md +8 -0
- data/Rakefile +19 -0
- data/identity_cache.gemspec +2 -1
- data/lib/{belongs_to_caching.rb → identity_cache/belongs_to_caching.rb} +12 -8
- data/lib/identity_cache/cache_key_generation.rb +58 -0
- data/lib/identity_cache/configuration_dsl.rb +301 -0
- data/lib/identity_cache/memoized_cache_proxy.rb +118 -0
- data/lib/identity_cache/parent_model_expiration.rb +34 -0
- data/lib/identity_cache/query_api.rb +312 -0
- data/lib/identity_cache/version.rb +1 -1
- data/lib/identity_cache.rb +35 -631
- data/performance/cache_runner.rb +123 -0
- data/performance/cpu.rb +28 -0
- data/performance/externals.rb +45 -0
- data/performance/profile.rb +26 -0
- data/test/attribute_cache_test.rb +3 -3
- data/test/fetch_multi_test.rb +13 -39
- data/test/fetch_multi_with_batched_associations_test.rb +236 -0
- data/test/fetch_test.rb +1 -1
- data/test/helpers/active_record_objects.rb +43 -0
- data/test/helpers/cache.rb +3 -12
- data/test/helpers/database_connection.rb +2 -1
- data/test/index_cache_test.rb +7 -0
- data/test/memoized_cache_proxy_test.rb +46 -1
- data/test/normalized_has_many_test.rb +13 -0
- data/test/recursive_denormalized_has_many_test.rb +17 -2
- data/test/save_test.rb +2 -2
- data/test/schema_change_test.rb +8 -28
- data/test/test_helper.rb +49 -43
- metadata +76 -76
- data/lib/memoized_cache_proxy.rb +0 -71
@@ -6,7 +6,7 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
6
6
|
IdentityCache.cache_backend = Rails.cache
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
9
|
+
def test_changing_default_cache
|
10
10
|
IdentityCache.cache_backend = ActiveSupport::Cache::MemoryStore.new
|
11
11
|
IdentityCache.cache.write('foo', 'bar')
|
12
12
|
assert_equal 'bar', IdentityCache.cache.read('foo')
|
@@ -21,6 +21,17 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def test_read_should_short_circuit_on_falsy_memoized_values
|
25
|
+
Rails.cache.expects(:read).never
|
26
|
+
|
27
|
+
IdentityCache.cache.with_memoization do
|
28
|
+
IdentityCache.cache.write('foo', nil)
|
29
|
+
assert_equal nil, IdentityCache.cache.read('foo')
|
30
|
+
IdentityCache.cache.write('bar', false)
|
31
|
+
assert_equal false, IdentityCache.cache.read('bar')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
24
35
|
def test_read_should_try_memcached_on_not_memoized_values
|
25
36
|
Rails.cache.expects(:read).with('foo').returns('bar')
|
26
37
|
|
@@ -40,6 +51,29 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
40
51
|
end
|
41
52
|
end
|
42
53
|
|
54
|
+
def test_read_should_memoize_values
|
55
|
+
IdentityCache.cache_backend = backend = ActiveSupport::Cache::MemoryStore.new
|
56
|
+
backend.write('foo', 'bar')
|
57
|
+
|
58
|
+
IdentityCache.cache.with_memoization do
|
59
|
+
assert_equal 'bar', IdentityCache.cache.read('foo')
|
60
|
+
backend.delete('foo')
|
61
|
+
assert_equal 'bar', IdentityCache.cache.read('foo')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_read_multi_should_memoize_values
|
66
|
+
IdentityCache.cache_backend = backend = ActiveSupport::Cache::MemoryStore.new
|
67
|
+
backend.write('foo', 'bar')
|
68
|
+
|
69
|
+
IdentityCache.cache.with_memoization do
|
70
|
+
assert_equal({'foo' => 'bar'}, IdentityCache.cache.read_multi('foo', 'fooz'))
|
71
|
+
backend.delete('foo')
|
72
|
+
backend.write('fooz', 'baz')
|
73
|
+
assert_equal({'foo' => 'bar'}, IdentityCache.cache.read_multi('foo', 'fooz'))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
43
77
|
def test_read_multi_with_partially_memoized_should_read_missing_keys_from_memcache
|
44
78
|
IdentityCache.cache.write('foo', 'bar')
|
45
79
|
Rails.cache.write('fooz', 'baz')
|
@@ -49,6 +83,17 @@ class MemoizedCacheProxyTest < IdentityCache::TestCase
|
|
49
83
|
end
|
50
84
|
end
|
51
85
|
|
86
|
+
def test_read_multi_with_blank_values_should_not_hit_the_cache_engine
|
87
|
+
Rails.cache.expects(:read_multi).never
|
88
|
+
|
89
|
+
IdentityCache.cache.with_memoization do
|
90
|
+
IdentityCache.cache.write('foo', [])
|
91
|
+
IdentityCache.cache.write('bar', false)
|
92
|
+
IdentityCache.cache.write('baz', {})
|
93
|
+
assert_equal({'foo' => [], 'bar' => false, 'baz' => {}}, IdentityCache.cache.read_multi('foo', 'bar', 'baz'))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
52
97
|
def test_with_memoization_should_not_clear_rails_cache_when_the_block_ends
|
53
98
|
IdentityCache.cache.with_memoization do
|
54
99
|
IdentityCache.cache.write('foo', 'bar')
|
@@ -26,6 +26,18 @@ class NormalizedHasManyTest < IdentityCache::TestCase
|
|
26
26
|
def test_defining_a_denormalized_has_many_cache_caches_the_list_of_associated_ids_on_the_parent_record_during_cache_miss
|
27
27
|
fetched_record = Record.fetch(@record.id)
|
28
28
|
assert_equal [2, 1], fetched_record.cached_associated_record_ids
|
29
|
+
assert_equal false, fetched_record.associated_records.loaded?
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_fetching_associated_ids_will_populate_the_value_if_the_record_isnt_from_the_cache
|
33
|
+
assert_equal [2, 1], @record.fetch_associated_record_ids
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_fetching_associated_ids_will_use_the_cached_value_if_the_record_is_from_the_cache
|
37
|
+
@record = Record.fetch(@record.id)
|
38
|
+
assert_queries(0) do
|
39
|
+
assert_equal [2, 1], @record.fetch_associated_record_ids
|
40
|
+
end
|
29
41
|
end
|
30
42
|
|
31
43
|
def test_the_cached_the_list_of_associated_ids_on_the_parent_record_should_not_be_populated_by_default
|
@@ -122,4 +134,5 @@ class NormalizedHasManyTest < IdentityCache::TestCase
|
|
122
134
|
IdentityCache.cache.expects(:delete).with(@record.primary_cache_index_key).once
|
123
135
|
@not_cached.save
|
124
136
|
end
|
137
|
+
|
125
138
|
end
|
@@ -67,14 +67,22 @@ class RecursiveDenormalizedHasManyTest < IdentityCache::TestCase
|
|
67
67
|
|
68
68
|
def test_saving_child_record_should_expire_parent_record
|
69
69
|
IdentityCache.cache.expects(:delete).with(@record.primary_cache_index_key)
|
70
|
-
|
70
|
+
if AssociatedRecord.primary_cache_index_enabled
|
71
|
+
IdentityCache.cache.expects(:delete).with(@associated_record.primary_cache_index_key)
|
72
|
+
else
|
73
|
+
IdentityCache.cache.expects(:delete).with(@associated_record.primary_cache_index_key).never
|
74
|
+
end
|
71
75
|
@associated_record.name = 'different'
|
72
76
|
@associated_record.save!
|
73
77
|
end
|
74
78
|
|
75
79
|
def test_saving_grand_child_record_should_expire_parent_record
|
76
80
|
IdentityCache.cache.expects(:delete).with(@record.primary_cache_index_key)
|
77
|
-
|
81
|
+
if AssociatedRecord.primary_cache_index_enabled
|
82
|
+
IdentityCache.cache.expects(:delete).with(@associated_record.primary_cache_index_key)
|
83
|
+
else
|
84
|
+
IdentityCache.cache.expects(:delete).with(@associated_record.primary_cache_index_key).never
|
85
|
+
end
|
78
86
|
IdentityCache.cache.expects(:delete).with(@deeply_associated_record.primary_cache_index_key)
|
79
87
|
@deeply_associated_record.name = 'different'
|
80
88
|
@deeply_associated_record.save!
|
@@ -98,3 +106,10 @@ class RecursiveNormalizedHasManyTest < IdentityCache::TestCase
|
|
98
106
|
record_from_cache_miss = Record.fetch(@record.id)
|
99
107
|
end
|
100
108
|
end
|
109
|
+
|
110
|
+
class DisabledPrimaryIndexTest < RecursiveDenormalizedHasManyTest
|
111
|
+
def setup
|
112
|
+
super
|
113
|
+
AssociatedRecord.disable_primary_cache_index
|
114
|
+
end
|
115
|
+
end
|
data/test/save_test.rb
CHANGED
@@ -7,7 +7,7 @@ class SaveTest < IdentityCache::TestCase
|
|
7
7
|
Record.cache_index :id, :title, :unique => true
|
8
8
|
|
9
9
|
@record = Record.create(:title => 'bob')
|
10
|
-
@blob_key = "IDC:blob:Record:#{cache_hash("created_at:datetime,id:integer,title:string,updated_at:datetime")}:1"
|
10
|
+
@blob_key = "IDC:blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:1"
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_create
|
@@ -16,7 +16,7 @@ class SaveTest < IdentityCache::TestCase
|
|
16
16
|
|
17
17
|
IdentityCache.cache.expects(:delete).with("IDC:index:Record:id/title:#{cache_hash('2/bob')}")
|
18
18
|
IdentityCache.cache.expects(:delete).with("IDC:index:Record:title:#{cache_hash('bob')}")
|
19
|
-
IdentityCache.cache.expects(:delete).with("IDC:blob:Record:#{cache_hash("created_at:datetime,id:integer,title:string,updated_at:datetime")}:2").once
|
19
|
+
IdentityCache.cache.expects(:delete).with("IDC:blob:Record:#{cache_hash("created_at:datetime,id:integer,record_id:integer,title:string,updated_at:datetime")}:2").once
|
20
20
|
@record.save
|
21
21
|
end
|
22
22
|
|
data/test/schema_change_test.rb
CHANGED
@@ -39,29 +39,22 @@ class SchemaChangeTest < IdentityCache::TestCase
|
|
39
39
|
AssociatedRecord.reset_column_information
|
40
40
|
DeeplyAssociatedRecord.reset_column_information
|
41
41
|
|
42
|
-
AssociatedRecord.
|
43
|
-
Record.
|
42
|
+
AssociatedRecord.send(:instance_variable_set, :@rails_cache_key_prefix, nil)
|
43
|
+
Record.send(:instance_variable_set, :@rails_cache_key_prefix, nil)
|
44
44
|
end
|
45
45
|
|
46
|
-
def
|
46
|
+
def test_schema_changes_on_embedded_association_should_cause_cache_miss_for_old_cached_objects
|
47
47
|
record = Record.fetch(@record.id)
|
48
48
|
record.fetch_associated
|
49
49
|
|
50
50
|
AddColumnToChild.new.up
|
51
51
|
read_new_schema
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
# SHOW TABLES LIKE 'associated_records'
|
56
|
-
# SELECT `associated_records`.* FROM `associated_records` WHERE `associated_records`.`record_id` = 1 ORDER BY id ASC LIMIT 1.
|
57
|
-
assert_queries(3) do
|
58
|
-
assert_nothing_raised { record.fetch_associated.shiny }
|
59
|
-
end
|
60
|
-
|
61
|
-
assert_no_queries { record.fetch_associated.shiny }
|
53
|
+
Record.expects(:resolve_cache_miss).returns(@record)
|
54
|
+
record = Record.fetch(@record.id)
|
62
55
|
end
|
63
56
|
|
64
|
-
def
|
57
|
+
def test_schema_changes_on_deeply_embedded_association_should_cause_cache_miss_for_old_cached_objects
|
65
58
|
record = Record.fetch(@record.id)
|
66
59
|
associated_record_from_cache = record.fetch_associated
|
67
60
|
associated_record_from_cache.fetch_deeply_associated_records
|
@@ -69,20 +62,7 @@ class SchemaChangeTest < IdentityCache::TestCase
|
|
69
62
|
AddColumnToDeepChild.new.up
|
70
63
|
read_new_schema
|
71
64
|
|
72
|
-
|
73
|
-
|
74
|
-
# SHOW FULL FIELDS FROM `associated_records`
|
75
|
-
# SHOW TABLES LIKE 'deeply_associated_records'
|
76
|
-
# SELECT `deeply_associated_records`.* FROM `deeply_associated_records` WHERE `deeply_associated_records`.`associated_record_id` = 1 ORDER BY name DESC.
|
77
|
-
assert_queries(4) do
|
78
|
-
assert_nothing_raised do
|
79
|
-
associated_record_from_cache.fetch_deeply_associated_records.map(&:new_column)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
assert_no_queries do
|
84
|
-
associated_record_from_cache.fetch_deeply_associated_records.each{ |obj| assert_nil obj.new_column }
|
85
|
-
record.fetch_associated.fetch_deeply_associated_records.each{ |obj| assert_nil obj.new_column }
|
86
|
-
end
|
65
|
+
Record.expects(:resolve_cache_miss).returns(@record)
|
66
|
+
record = Record.fetch(@record.id)
|
87
67
|
end
|
88
68
|
end
|
data/test/test_helper.rb
CHANGED
@@ -3,6 +3,7 @@ require 'mocha/setup'
|
|
3
3
|
require 'active_record'
|
4
4
|
require 'helpers/cache'
|
5
5
|
require 'helpers/database_connection'
|
6
|
+
require 'helpers/active_record_objects'
|
6
7
|
|
7
8
|
require File.dirname(__FILE__) + '/../lib/identity_cache'
|
8
9
|
|
@@ -15,8 +16,22 @@ else
|
|
15
16
|
end
|
16
17
|
|
17
18
|
DatabaseConnection.setup
|
19
|
+
ActiveSupport::Cache::Store.instrument = true
|
20
|
+
|
21
|
+
# This patches AR::MemcacheStore to notify AS::Notifications upon read_multis like the rest of rails does
|
22
|
+
class ActiveSupport::Cache::MemCacheStore
|
23
|
+
def read_multi_with_instrumentation(*args, &block)
|
24
|
+
instrument("read_multi", "MULTI", {:keys => args}) do
|
25
|
+
read_multi_without_instrumentation(*args, &block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
alias_method_chain :read_multi, :instrumentation
|
30
|
+
end
|
18
31
|
|
19
32
|
class IdentityCache::TestCase < MiniTest::Unit::TestCase
|
33
|
+
include ActiveRecordObjects
|
34
|
+
|
20
35
|
def setup
|
21
36
|
DatabaseConnection.drop_tables
|
22
37
|
DatabaseConnection.create_tables
|
@@ -26,13 +41,7 @@ class IdentityCache::TestCase < MiniTest::Unit::TestCase
|
|
26
41
|
|
27
42
|
def teardown
|
28
43
|
IdentityCache.cache.clear
|
29
|
-
|
30
|
-
ActiveSupport::Dependencies.clear
|
31
|
-
Object.send :remove_const, 'DeeplyAssociatedRecord'
|
32
|
-
Object.send :remove_const, 'PolymorphicRecord'
|
33
|
-
Object.send :remove_const, 'AssociatedRecord'
|
34
|
-
Object.send :remove_const, 'NotCachedRecord'
|
35
|
-
Object.send :remove_const, 'Record'
|
44
|
+
teardown_models
|
36
45
|
end
|
37
46
|
|
38
47
|
def assert_nothing_raised
|
@@ -46,10 +55,27 @@ class IdentityCache::TestCase < MiniTest::Unit::TestCase
|
|
46
55
|
def assert_queries(num = 1)
|
47
56
|
counter = SQLCounter.new
|
48
57
|
subscriber = ActiveSupport::Notifications.subscribe('sql.active_record', counter)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
58
|
+
exception = false
|
59
|
+
yield
|
60
|
+
rescue => e
|
61
|
+
exception = true
|
62
|
+
raise
|
63
|
+
ensure
|
64
|
+
ActiveSupport::Notifications.unsubscribe(subscriber)
|
65
|
+
assert_equal num, counter.log.size, "#{counter.log.size} instead of #{num} queries were executed.#{counter.log.size == 0 ? '' : "\nQueries:\n#{counter.log.join("\n")}"}" unless exception
|
66
|
+
end
|
67
|
+
|
68
|
+
def assert_memcache_operations(num)
|
69
|
+
counter = CacheCounter.new
|
70
|
+
subscriber = ActiveSupport::Notifications.subscribe(/cache_.*\.active_support/, counter)
|
71
|
+
exception = false
|
72
|
+
yield
|
73
|
+
rescue => e
|
74
|
+
exception = true
|
75
|
+
raise
|
76
|
+
ensure
|
77
|
+
ActiveSupport::Notifications.unsubscribe(subscriber)
|
78
|
+
assert_equal num, counter.log.size, "#{counter.log.size} instead of #{num} memcache operations were executed. #{counter.log.size == 0 ? '' : "\nOperations:\n#{counter.log.join("\n")}"}" unless exception
|
53
79
|
end
|
54
80
|
|
55
81
|
def assert_no_queries
|
@@ -61,38 +87,6 @@ class IdentityCache::TestCase < MiniTest::Unit::TestCase
|
|
61
87
|
def cache_hash(key)
|
62
88
|
CityHash.hash64(key)
|
63
89
|
end
|
64
|
-
|
65
|
-
private
|
66
|
-
def setup_models
|
67
|
-
Object.send :const_set, 'DeeplyAssociatedRecord', Class.new(ActiveRecord::Base).tap {|klass|
|
68
|
-
klass.send :include, IdentityCache
|
69
|
-
klass.belongs_to :associated_record
|
70
|
-
}
|
71
|
-
|
72
|
-
Object.send :const_set, 'AssociatedRecord', Class.new(ActiveRecord::Base).tap {|klass|
|
73
|
-
klass.send :include, IdentityCache
|
74
|
-
klass.belongs_to :record
|
75
|
-
klass.has_many :deeply_associated_records, :order => "name DESC"
|
76
|
-
}
|
77
|
-
|
78
|
-
Object.send :const_set, 'NotCachedRecord', Class.new(ActiveRecord::Base).tap {|klass|
|
79
|
-
klass.belongs_to :record, :touch => true
|
80
|
-
}
|
81
|
-
|
82
|
-
Object.send :const_set, 'PolymorphicRecord', Class.new(ActiveRecord::Base).tap {|klass|
|
83
|
-
klass.belongs_to :owner, :polymorphic => true
|
84
|
-
}
|
85
|
-
|
86
|
-
Object.send :const_set, 'Record', Class.new(ActiveRecord::Base).tap {|klass|
|
87
|
-
klass.send :include, IdentityCache
|
88
|
-
klass.belongs_to :record
|
89
|
-
klass.has_many :associated_records, :order => "id DESC"
|
90
|
-
klass.has_many :not_cached_records, :order => "id DESC"
|
91
|
-
klass.has_many :polymorphic_records, :as => 'owner'
|
92
|
-
klass.has_one :polymorphic_record, :as => 'owner'
|
93
|
-
klass.has_one :associated, :class_name => 'AssociatedRecord', :order => "id ASC"
|
94
|
-
}
|
95
|
-
end
|
96
90
|
end
|
97
91
|
|
98
92
|
class SQLCounter
|
@@ -120,3 +114,15 @@ class SQLCounter
|
|
120
114
|
self.log << sql
|
121
115
|
end
|
122
116
|
end
|
117
|
+
|
118
|
+
class CacheCounter
|
119
|
+
attr_accessor :log
|
120
|
+
|
121
|
+
def initialize()
|
122
|
+
@log = []
|
123
|
+
end
|
124
|
+
|
125
|
+
def call(name, start, finish, message_id, values)
|
126
|
+
self.log << (values[:keys].try(:join, ', ') || values[:key])
|
127
|
+
end
|
128
|
+
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: identity_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.0.2
|
4
|
+
version: 0.0.3
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Camilo Lopez
|
@@ -13,152 +12,148 @@ authors:
|
|
13
12
|
autorequire:
|
14
13
|
bindir: bin
|
15
14
|
cert_chain: []
|
16
|
-
date: 2013-
|
15
|
+
date: 2013-06-10 00:00:00.000000000 Z
|
17
16
|
dependencies:
|
18
17
|
- !ruby/object:Gem::Dependency
|
19
|
-
prerelease: false
|
20
18
|
name: ar_transaction_changes
|
21
|
-
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirement: !ruby/object:Gem::Requirement
|
23
20
|
requirements:
|
24
21
|
- - '='
|
25
22
|
- !ruby/object:Gem::Version
|
26
23
|
version: 0.0.1
|
27
|
-
|
28
|
-
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
29
27
|
requirements:
|
30
28
|
- - '='
|
31
29
|
- !ruby/object:Gem::Version
|
32
30
|
version: 0.0.1
|
33
|
-
none: false
|
34
31
|
- !ruby/object:Gem::Dependency
|
35
|
-
prerelease: false
|
36
32
|
name: activerecord
|
37
|
-
|
38
|
-
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
39
34
|
requirements:
|
40
35
|
- - '='
|
41
36
|
- !ruby/object:Gem::Version
|
42
37
|
version: 3.2.13
|
43
|
-
|
44
|
-
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
45
41
|
requirements:
|
46
42
|
- - '='
|
47
43
|
- !ruby/object:Gem::Version
|
48
44
|
version: 3.2.13
|
49
|
-
none: false
|
50
45
|
- !ruby/object:Gem::Dependency
|
51
|
-
prerelease: false
|
52
46
|
name: activesupport
|
53
|
-
|
54
|
-
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
requirement: !ruby/object:Gem::Requirement
|
55
48
|
requirements:
|
56
49
|
- - '='
|
57
50
|
- !ruby/object:Gem::Version
|
58
51
|
version: 3.2.13
|
59
|
-
|
60
|
-
|
52
|
+
type: :runtime
|
53
|
+
prerelease: false
|
54
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
55
|
requirements:
|
62
56
|
- - '='
|
63
57
|
- !ruby/object:Gem::Version
|
64
58
|
version: 3.2.13
|
65
|
-
none: false
|
66
59
|
- !ruby/object:Gem::Dependency
|
67
|
-
prerelease: false
|
68
60
|
name: cityhash
|
69
|
-
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
requirement: !ruby/object:Gem::Requirement
|
71
62
|
requirements:
|
72
63
|
- - '='
|
73
64
|
- !ruby/object:Gem::Version
|
74
65
|
version: 0.6.0
|
75
|
-
|
76
|
-
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
69
|
requirements:
|
78
70
|
- - '='
|
79
71
|
- !ruby/object:Gem::Version
|
80
72
|
version: 0.6.0
|
81
|
-
none: false
|
82
73
|
- !ruby/object:Gem::Dependency
|
83
|
-
prerelease: false
|
84
74
|
name: memcache-client
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
85
80
|
type: :development
|
81
|
+
prerelease: false
|
86
82
|
version_requirements: !ruby/object:Gem::Requirement
|
87
83
|
requirements:
|
88
|
-
- -
|
84
|
+
- - '>='
|
89
85
|
- !ruby/object:Gem::Version
|
90
86
|
version: '0'
|
91
|
-
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: rake
|
92
89
|
requirement: !ruby/object:Gem::Requirement
|
93
90
|
requirements:
|
94
|
-
- -
|
91
|
+
- - '>='
|
95
92
|
- !ruby/object:Gem::Version
|
96
93
|
version: '0'
|
97
|
-
none: false
|
98
|
-
- !ruby/object:Gem::Dependency
|
99
|
-
prerelease: false
|
100
|
-
name: rake
|
101
94
|
type: :development
|
95
|
+
prerelease: false
|
102
96
|
version_requirements: !ruby/object:Gem::Requirement
|
103
97
|
requirements:
|
104
|
-
- -
|
98
|
+
- - '>='
|
105
99
|
- !ruby/object:Gem::Version
|
106
100
|
version: '0'
|
107
|
-
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: mocha
|
108
103
|
requirement: !ruby/object:Gem::Requirement
|
109
104
|
requirements:
|
110
|
-
- -
|
105
|
+
- - '='
|
111
106
|
- !ruby/object:Gem::Version
|
112
|
-
version:
|
113
|
-
none: false
|
114
|
-
- !ruby/object:Gem::Dependency
|
115
|
-
prerelease: false
|
116
|
-
name: mocha
|
107
|
+
version: 0.14.0
|
117
108
|
type: :development
|
109
|
+
prerelease: false
|
118
110
|
version_requirements: !ruby/object:Gem::Requirement
|
119
111
|
requirements:
|
120
|
-
- -
|
112
|
+
- - '='
|
121
113
|
- !ruby/object:Gem::Version
|
122
|
-
version:
|
123
|
-
|
114
|
+
version: 0.14.0
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: mysql2
|
124
117
|
requirement: !ruby/object:Gem::Requirement
|
125
118
|
requirements:
|
126
|
-
- -
|
119
|
+
- - '>='
|
127
120
|
- !ruby/object:Gem::Version
|
128
121
|
version: '0'
|
129
|
-
none: false
|
130
|
-
- !ruby/object:Gem::Dependency
|
131
|
-
prerelease: false
|
132
|
-
name: mysql2
|
133
122
|
type: :development
|
123
|
+
prerelease: false
|
134
124
|
version_requirements: !ruby/object:Gem::Requirement
|
135
125
|
requirements:
|
136
|
-
- -
|
126
|
+
- - '>='
|
137
127
|
- !ruby/object:Gem::Version
|
138
128
|
version: '0'
|
139
|
-
|
129
|
+
- !ruby/object:Gem::Dependency
|
130
|
+
name: debugger
|
140
131
|
requirement: !ruby/object:Gem::Requirement
|
141
132
|
requirements:
|
142
|
-
- -
|
133
|
+
- - '>='
|
143
134
|
- !ruby/object:Gem::Version
|
144
135
|
version: '0'
|
145
|
-
none: false
|
146
|
-
- !ruby/object:Gem::Dependency
|
147
|
-
prerelease: false
|
148
|
-
name: debugger
|
149
136
|
type: :development
|
137
|
+
prerelease: false
|
150
138
|
version_requirements: !ruby/object:Gem::Requirement
|
151
139
|
requirements:
|
152
|
-
- -
|
140
|
+
- - '>='
|
153
141
|
- !ruby/object:Gem::Version
|
154
142
|
version: '0'
|
155
|
-
|
143
|
+
- !ruby/object:Gem::Dependency
|
144
|
+
name: ruby-prof
|
156
145
|
requirement: !ruby/object:Gem::Requirement
|
157
146
|
requirements:
|
158
|
-
- -
|
147
|
+
- - '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - '>='
|
159
155
|
- !ruby/object:Gem::Version
|
160
156
|
version: '0'
|
161
|
-
none: false
|
162
157
|
description: Opt in read through ActiveRecord caching.
|
163
158
|
email:
|
164
159
|
- harry.brundage@shopify.com
|
@@ -174,16 +169,26 @@ files:
|
|
174
169
|
- README.md
|
175
170
|
- Rakefile
|
176
171
|
- identity_cache.gemspec
|
177
|
-
- lib/belongs_to_caching.rb
|
178
172
|
- lib/identity_cache.rb
|
173
|
+
- lib/identity_cache/belongs_to_caching.rb
|
174
|
+
- lib/identity_cache/cache_key_generation.rb
|
175
|
+
- lib/identity_cache/configuration_dsl.rb
|
176
|
+
- lib/identity_cache/memoized_cache_proxy.rb
|
177
|
+
- lib/identity_cache/parent_model_expiration.rb
|
178
|
+
- lib/identity_cache/query_api.rb
|
179
179
|
- lib/identity_cache/version.rb
|
180
|
-
-
|
180
|
+
- performance/cache_runner.rb
|
181
|
+
- performance/cpu.rb
|
182
|
+
- performance/externals.rb
|
183
|
+
- performance/profile.rb
|
181
184
|
- test/attribute_cache_test.rb
|
182
185
|
- test/cache_fetch_includes_test.rb
|
183
186
|
- test/denormalized_has_many_test.rb
|
184
187
|
- test/denormalized_has_one_test.rb
|
185
188
|
- test/fetch_multi_test.rb
|
189
|
+
- test/fetch_multi_with_batched_associations_test.rb
|
186
190
|
- test/fetch_test.rb
|
191
|
+
- test/helpers/active_record_objects.rb
|
187
192
|
- test/helpers/cache.rb
|
188
193
|
- test/helpers/database_connection.rb
|
189
194
|
- test/identity_cache_test.rb
|
@@ -197,33 +202,26 @@ files:
|
|
197
202
|
- test/test_helper.rb
|
198
203
|
homepage: https://github.com/Shopify/identity_cache
|
199
204
|
licenses: []
|
205
|
+
metadata: {}
|
200
206
|
post_install_message:
|
201
207
|
rdoc_options: []
|
202
208
|
require_paths:
|
203
209
|
- lib
|
204
210
|
required_ruby_version: !ruby/object:Gem::Requirement
|
205
211
|
requirements:
|
206
|
-
- -
|
212
|
+
- - '>='
|
207
213
|
- !ruby/object:Gem::Version
|
208
|
-
segments:
|
209
|
-
- 0
|
210
|
-
hash: -901854368761295247
|
211
214
|
version: '0'
|
212
|
-
none: false
|
213
215
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
214
216
|
requirements:
|
215
|
-
- -
|
217
|
+
- - '>='
|
216
218
|
- !ruby/object:Gem::Version
|
217
|
-
segments:
|
218
|
-
- 0
|
219
|
-
hash: -901854368761295247
|
220
219
|
version: '0'
|
221
|
-
none: false
|
222
220
|
requirements: []
|
223
221
|
rubyforge_project:
|
224
|
-
rubygems_version:
|
222
|
+
rubygems_version: 2.0.0
|
225
223
|
signing_key:
|
226
|
-
specification_version:
|
224
|
+
specification_version: 4
|
227
225
|
summary: IdentityCache lets you specify how you want to cache your model objects,
|
228
226
|
at the model level, and adds a number of convenience methods for accessing those
|
229
227
|
objects through the cache. Memcached is used as the backend cache store, and the
|
@@ -234,7 +232,9 @@ test_files:
|
|
234
232
|
- test/denormalized_has_many_test.rb
|
235
233
|
- test/denormalized_has_one_test.rb
|
236
234
|
- test/fetch_multi_test.rb
|
235
|
+
- test/fetch_multi_with_batched_associations_test.rb
|
237
236
|
- test/fetch_test.rb
|
237
|
+
- test/helpers/active_record_objects.rb
|
238
238
|
- test/helpers/cache.rb
|
239
239
|
- test/helpers/database_connection.rb
|
240
240
|
- test/identity_cache_test.rb
|