identity_cache 0.2.1 → 0.2.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
- checksums.yaml.gz.sig +0 -0
- data/README.md +1 -1
- data/identity_cache.gemspec +1 -1
- data/lib/identity_cache/belongs_to_caching.rb +1 -1
- data/lib/identity_cache/cache_fetcher.rb +7 -4
- data/lib/identity_cache/configuration_dsl.rb +1 -1
- data/lib/identity_cache/fallback_fetcher.rb +5 -5
- data/lib/identity_cache/query_api.rb +3 -3
- data/lib/identity_cache/version.rb +1 -1
- data/lib/identity_cache.rb +8 -4
- data/test/readonly_test.rb +104 -0
- data.tar.gz.sig +0 -0
- metadata +5 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e49bcbf1656c4c055a0c04174a770650888b3349
|
4
|
+
data.tar.gz: ea93b60ce00ff52ea21440ce811a0f1c545cb8b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e31e64a5b480adafd760b0364d4881d22fcb4ca09eed09bde2c810d63d5c4db959a06812bd6ec8ff8ebb5f3b58e55b30fde78c2b0c4dfa3d018876849156c263
|
7
|
+
data.tar.gz: 2fd22fce69151ea24d0836d0da19af7c36762c83e73ec7282e59b8298ee55c27e8196b706f9c64ea4152e331d123d0b8c6147d3625b452c6fbf905119bdebbe3
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -55,7 +55,7 @@ Note: You must include the IdentityCache module into the classes where you want
|
|
55
55
|
|
56
56
|
### Secondary Indexes
|
57
57
|
|
58
|
-
|
58
|
+
IdentityCache lets you lookup records by fields other than `id`. You can have multiple of these indexes with any other combination of fields:
|
59
59
|
|
60
60
|
``` ruby
|
61
61
|
class Product < ActiveRecord::Base
|
data/identity_cache.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_dependency('ar_transaction_changes', '~> 1.0')
|
19
19
|
gem.add_dependency('activerecord', '>= 3.2')
|
20
|
-
gem.
|
20
|
+
gem.add_development_dependency('memcached', '~> 1.8.0')
|
21
21
|
|
22
22
|
gem.add_development_dependency('memcached_store', '~> 0.12.6')
|
23
23
|
gem.add_development_dependency('rake')
|
@@ -26,7 +26,7 @@ module IdentityCache
|
|
26
26
|
def build_normalized_belongs_to_cache(association, options)
|
27
27
|
self.class_eval(<<-CODE, __FILE__, __LINE__ + 1)
|
28
28
|
def #{options[:cached_accessor_name]}
|
29
|
-
if IdentityCache.
|
29
|
+
if IdentityCache.should_use_cache? && #{options[:foreign_key]}.present? && !association(:#{association}).loaded?
|
30
30
|
self.#{association} = #{options[:association_class]}.fetch_by_id(#{options[:foreign_key]})
|
31
31
|
else
|
32
32
|
#{association}
|
@@ -7,15 +7,15 @@ module IdentityCache
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def write(key, value)
|
10
|
-
@cache_backend.write(key, value)
|
10
|
+
@cache_backend.write(key, value) if IdentityCache.should_update_cache?
|
11
11
|
end
|
12
12
|
|
13
13
|
def delete(key)
|
14
|
-
@cache_backend.write(key, IdentityCache::DELETED, :expires_in => IdentityCache::DELETED_TTL.seconds)
|
14
|
+
@cache_backend.write(key, IdentityCache::DELETED, :expires_in => IdentityCache::DELETED_TTL.seconds) if IdentityCache.should_update_cache?
|
15
15
|
end
|
16
16
|
|
17
17
|
def clear
|
18
|
-
@cache_backend.clear
|
18
|
+
@cache_backend.clear if IdentityCache.should_update_cache?
|
19
19
|
end
|
20
20
|
|
21
21
|
def fetch_multi(keys, &block)
|
@@ -34,6 +34,8 @@ module IdentityCache
|
|
34
34
|
break
|
35
35
|
end
|
36
36
|
result = yield
|
37
|
+
break unless IdentityCache.should_update_cache?
|
38
|
+
result
|
37
39
|
end
|
38
40
|
unless yielded
|
39
41
|
result = yield
|
@@ -66,6 +68,7 @@ module IdentityCache
|
|
66
68
|
end
|
67
69
|
|
68
70
|
break if updates.empty?
|
71
|
+
break unless IdentityCache.should_update_cache?
|
69
72
|
updates
|
70
73
|
end
|
71
74
|
result
|
@@ -78,7 +81,7 @@ module IdentityCache
|
|
78
81
|
end
|
79
82
|
|
80
83
|
def add(key, value)
|
81
|
-
@cache_backend.write(key, value, :unless_exist => true)
|
84
|
+
@cache_backend.write(key, value, :unless_exist => true) if IdentityCache.should_update_cache?
|
82
85
|
end
|
83
86
|
end
|
84
87
|
end
|
@@ -247,7 +247,7 @@ module IdentityCache
|
|
247
247
|
end
|
248
248
|
|
249
249
|
def #{options[:cached_accessor_name]}
|
250
|
-
if IdentityCache.
|
250
|
+
if IdentityCache.should_use_cache? || #{association}.loaded?
|
251
251
|
#{options[:population_method_name]} unless @#{options[:ids_variable_name]} || @#{options[:records_variable_name]}
|
252
252
|
@#{options[:records_variable_name]} ||= #{options[:association_class]}.fetch_multi(@#{options[:ids_variable_name]})
|
253
253
|
else
|
@@ -7,15 +7,15 @@ module IdentityCache
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def write(key, value)
|
10
|
-
@cache_backend.write(key, value)
|
10
|
+
@cache_backend.write(key, value) if IdentityCache.should_update_cache?
|
11
11
|
end
|
12
12
|
|
13
13
|
def delete(key)
|
14
|
-
@cache_backend.delete(key)
|
14
|
+
@cache_backend.delete(key) if IdentityCache.should_update_cache?
|
15
15
|
end
|
16
16
|
|
17
17
|
def clear
|
18
|
-
@cache_backend.clear
|
18
|
+
@cache_backend.clear if IdentityCache.should_update_cache?
|
19
19
|
end
|
20
20
|
|
21
21
|
def fetch_multi(keys, &block)
|
@@ -24,7 +24,7 @@ module IdentityCache
|
|
24
24
|
unless missed_keys.empty?
|
25
25
|
replacement_results = yield missed_keys
|
26
26
|
missed_keys.zip(replacement_results) do |key, replacement_result|
|
27
|
-
@cache_backend.write(key, replacement_result)
|
27
|
+
@cache_backend.write(key, replacement_result) if IdentityCache.should_update_cache?
|
28
28
|
results[key] = replacement_result
|
29
29
|
end
|
30
30
|
end
|
@@ -35,7 +35,7 @@ module IdentityCache
|
|
35
35
|
result = @cache_backend.read(key)
|
36
36
|
if result.nil?
|
37
37
|
result = yield
|
38
|
-
@cache_backend.write(key, result)
|
38
|
+
@cache_backend.write(key, result) if IdentityCache.should_update_cache?
|
39
39
|
end
|
40
40
|
result
|
41
41
|
end
|
@@ -22,7 +22,7 @@ module IdentityCache
|
|
22
22
|
def fetch_by_id(id)
|
23
23
|
return unless id
|
24
24
|
raise NotImplementedError, "fetching needs the primary index enabled" unless primary_cache_index_enabled
|
25
|
-
if IdentityCache.
|
25
|
+
if IdentityCache.should_use_cache?
|
26
26
|
|
27
27
|
require_if_necessary do
|
28
28
|
object = nil
|
@@ -50,7 +50,7 @@ module IdentityCache
|
|
50
50
|
raise NotImplementedError, "fetching needs the primary index enabled" unless primary_cache_index_enabled
|
51
51
|
options = ids.extract_options!
|
52
52
|
ids.flatten!(1)
|
53
|
-
records = if IdentityCache.
|
53
|
+
records = if IdentityCache.should_use_cache?
|
54
54
|
require_if_necessary do
|
55
55
|
cache_keys = ids.map {|id| rails_cache_key(id) }
|
56
56
|
key_to_id_map = Hash[ cache_keys.zip(ids) ]
|
@@ -313,7 +313,7 @@ module IdentityCache
|
|
313
313
|
|
314
314
|
def fetch_recursively_cached_association(ivar_name, association_name) # :nodoc:
|
315
315
|
ivar_full_name = :"@#{ivar_name}"
|
316
|
-
if IdentityCache.
|
316
|
+
if IdentityCache.should_use_cache?
|
317
317
|
populate_recursively_cached_association(ivar_name, association_name)
|
318
318
|
assoc = IdentityCache.unmap_cached_nil_for(instance_variable_get(ivar_full_name))
|
319
319
|
assoc.is_a?(ActiveRecord::Associations::CollectionAssociation) ? assoc.reader : assoc
|
data/lib/identity_cache.rb
CHANGED
@@ -69,8 +69,12 @@ module IdentityCache
|
|
69
69
|
@logger || Rails.logger
|
70
70
|
end
|
71
71
|
|
72
|
-
def
|
73
|
-
!readonly &&
|
72
|
+
def should_update_cache? # :nodoc:
|
73
|
+
!readonly && should_use_cache?
|
74
|
+
end
|
75
|
+
|
76
|
+
def should_use_cache? # :nodoc:
|
77
|
+
ActiveRecord::Base.connection.open_transactions == 0
|
74
78
|
end
|
75
79
|
|
76
80
|
# Cache retrieval and miss resolver primitive; given a key it will try to
|
@@ -81,7 +85,7 @@ module IdentityCache
|
|
81
85
|
# +key+ A cache key string
|
82
86
|
#
|
83
87
|
def fetch(key)
|
84
|
-
if
|
88
|
+
if should_use_cache?
|
85
89
|
unmap_cached_nil_for(cache.fetch(key) { map_cached_nil_for yield })
|
86
90
|
else
|
87
91
|
yield
|
@@ -105,7 +109,7 @@ module IdentityCache
|
|
105
109
|
keys.flatten!(1)
|
106
110
|
return {} if keys.size == 0
|
107
111
|
|
108
|
-
result = if
|
112
|
+
result = if should_use_cache?
|
109
113
|
fetch_in_batches(keys) do |missed_keys|
|
110
114
|
results = yield missed_keys
|
111
115
|
results.map {|e| map_cached_nil_for e }
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ReadonlyTest < IdentityCache::TestCase
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
IdentityCache.readonly = true
|
7
|
+
@key, @value = 'foo', 'bar'
|
8
|
+
@record = Item.new
|
9
|
+
@record.id = 1
|
10
|
+
@record.title = 'bob'
|
11
|
+
@bob = Item.create!(:title => 'bob')
|
12
|
+
@joe = Item.create!(:title => 'joe')
|
13
|
+
@fred = Item.create!(:title => 'fred')
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
IdentityCache.readonly = nil
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_write_should_not_update_cache
|
22
|
+
assert_memcache_operations(0) do
|
23
|
+
fetcher.write(@key, @value)
|
24
|
+
end
|
25
|
+
assert_nil backend.read(@key)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_delete_should_not_update_cache
|
29
|
+
backend.write(@key, @value)
|
30
|
+
assert_memcache_operations(0) do
|
31
|
+
fetcher.delete(@key)
|
32
|
+
end
|
33
|
+
assert_equal @value, backend.read(@key)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_clear_should_not_update_cache
|
37
|
+
backend.write(@key, @value)
|
38
|
+
assert_memcache_operations(0) do
|
39
|
+
fetcher.clear
|
40
|
+
end
|
41
|
+
assert_equal @value, backend.read(@key)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_fetch_should_not_update_cache
|
45
|
+
fetch = Spy.on(IdentityCache.cache, :fetch).and_call_through
|
46
|
+
Item.expects(:resolve_cache_miss).with(1).once.returns(@record)
|
47
|
+
|
48
|
+
assert_readonly_fetch do
|
49
|
+
assert_equal @record, Item.fetch(1)
|
50
|
+
end
|
51
|
+
assert_nil backend.read(@record.primary_cache_index_key)
|
52
|
+
assert fetch.has_been_called_with?(@record.primary_cache_index_key)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_fetch_multi_should_not_update_cache
|
56
|
+
fetch_multi = Spy.on(IdentityCache.cache, :fetch_multi).and_call_through
|
57
|
+
|
58
|
+
assert_readonly_fetch_multi do
|
59
|
+
assert_equal [@bob, @joe, @fred], Item.fetch_multi(@bob.id, @joe.id, @fred.id)
|
60
|
+
end
|
61
|
+
keys = [@bob, @joe, @fred].map(&:primary_cache_index_key)
|
62
|
+
assert_empty backend.read_multi(*keys)
|
63
|
+
assert fetch_multi.has_been_called_with?(*keys)
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
def assert_readonly_fetch
|
69
|
+
cas = Spy.on(backend, :cas).and_call_through
|
70
|
+
yield
|
71
|
+
assert cas.has_been_called?
|
72
|
+
end
|
73
|
+
|
74
|
+
def assert_readonly_fetch_multi
|
75
|
+
cas_multi = Spy.on(backend, :cas_multi).and_call_through
|
76
|
+
yield
|
77
|
+
assert cas_multi.has_been_called?
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class FallbackReadonlyTest < ReadonlyTest
|
82
|
+
def setup
|
83
|
+
super
|
84
|
+
IdentityCache.cache_backend = @backend = ActiveSupport::Cache::MemoryStore.new
|
85
|
+
end
|
86
|
+
|
87
|
+
protected
|
88
|
+
|
89
|
+
def assert_readonly_fetch
|
90
|
+
read = Spy.on(backend, :read).and_call_through
|
91
|
+
write = Spy.on(backend, :write).and_call_through
|
92
|
+
yield
|
93
|
+
assert read.has_been_called?
|
94
|
+
refute write.has_been_called?
|
95
|
+
end
|
96
|
+
|
97
|
+
def assert_readonly_fetch_multi
|
98
|
+
read_multi = Spy.on(backend, :read_multi).and_call_through
|
99
|
+
write = Spy.on(backend, :write).and_call_through
|
100
|
+
yield
|
101
|
+
assert read_multi.has_been_called?
|
102
|
+
refute write.has_been_called?
|
103
|
+
end
|
104
|
+
end
|
data.tar.gz.sig
CHANGED
Binary file
|
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.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Camilo Lopez
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
fl3hbtVFTqbOlwL9vy1fudXcolIE/ZTcxQ+er07ZFZdKCXayR9PPs64heamfn0fp
|
37
37
|
TConQSX2BnZdhIEYW+cKzEC/bLc=
|
38
38
|
-----END CERTIFICATE-----
|
39
|
-
date: 2014-
|
39
|
+
date: 2014-09-10 00:00:00.000000000 Z
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: ar_transaction_changes
|
@@ -73,7 +73,7 @@ dependencies:
|
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 1.8.0
|
76
|
-
type: :
|
76
|
+
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
@@ -247,6 +247,7 @@ files:
|
|
247
247
|
- test/normalized_belongs_to_test.rb
|
248
248
|
- test/normalized_has_many_test.rb
|
249
249
|
- test/normalized_has_one_test.rb
|
250
|
+
- test/readonly_test.rb
|
250
251
|
- test/recursive_denormalized_has_many_test.rb
|
251
252
|
- test/save_test.rb
|
252
253
|
- test/schema_change_test.rb
|
@@ -299,6 +300,7 @@ test_files:
|
|
299
300
|
- test/normalized_belongs_to_test.rb
|
300
301
|
- test/normalized_has_many_test.rb
|
301
302
|
- test/normalized_has_one_test.rb
|
303
|
+
- test/readonly_test.rb
|
302
304
|
- test/recursive_denormalized_has_many_test.rb
|
303
305
|
- test/save_test.rb
|
304
306
|
- test/schema_change_test.rb
|
metadata.gz.sig
CHANGED
Binary file
|