cache-object 0.0.3 → 0.0.4
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/cache-object.gemspec +1 -0
- data/lib/cache/object.rb +1 -0
- data/lib/cache/object/active_record.rb +4 -5
- data/lib/cache/object/adapter.rb +5 -1
- data/lib/cache/object/config.rb +2 -0
- data/lib/cache/object/instance_decorator.rb +2 -3
- data/lib/cache/object/multi_get.rb +36 -0
- data/lib/cache/object/version.rb +1 -1
- data/spec/cache/object/active_record_spec.rb +9 -2
- data/spec/cache/object/multi_get_spec.rb +57 -0
- data/spec/features/cache_object_spec.rb +29 -1
- data/spec/spec_helper.rb +5 -3
- metadata +18 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8ed3e3acf8e4c9fe23e4a3d0f73b067e1570318
|
4
|
+
data.tar.gz: d7f3afcb8be6c0d3065c97e7a1e7f027c25621bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b77a6a97aa5e46e6d9d01e16f97fd1e9f724c7029fc21c230ffc622f7bb9b67545cb81407b7010063329f5a3f9b881d949aafc3f1aebdcb3b00ef867097fbdb1
|
7
|
+
data.tar.gz: a0418a92720e49b01648b7bc6730f6d56070d8919c5845e8e32292de0d51197405521053952382d5ccde59e7925382f1a75ef45decde9e96fc4736ba14a58fa0
|
data/cache-object.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency "rake"
|
25
25
|
|
26
26
|
spec.add_development_dependency "rspec", ">= 3.0"
|
27
|
+
spec.add_development_dependency "rspec-collection_matchers", ">= 1.0"
|
27
28
|
spec.add_development_dependency "guard"
|
28
29
|
spec.add_development_dependency "guard-rspec"
|
29
30
|
spec.add_development_dependency "sqlite3"
|
data/lib/cache/object.rb
CHANGED
@@ -22,10 +22,6 @@ module Cache
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def load_from_cache(attributes)
|
25
|
-
attributes.each_pair do |key, value|
|
26
|
-
attributes[key] = value
|
27
|
-
end
|
28
|
-
|
29
25
|
@attributes = self.class.initialize_attributes(attributes)
|
30
26
|
@relation = nil
|
31
27
|
|
@@ -55,7 +51,6 @@ module Cache
|
|
55
51
|
module ClassMethods
|
56
52
|
def _load(args)
|
57
53
|
attributes = Marshal.load(args)
|
58
|
-
|
59
54
|
object = allocate
|
60
55
|
object.load_from_cache(attributes)
|
61
56
|
object
|
@@ -73,6 +68,10 @@ module Cache
|
|
73
68
|
end
|
74
69
|
end
|
75
70
|
|
71
|
+
def fetch_all(ids)
|
72
|
+
Cache::Object::MultiGet.new(self).fetch_all(ids)
|
73
|
+
end
|
74
|
+
|
76
75
|
def object_cache_on(*attrs)
|
77
76
|
self._object_cache_attr_mappings << attrs
|
78
77
|
define_singleton_method("find_by_#{attrs.join('_and_')}") do |*args|
|
data/lib/cache/object/adapter.rb
CHANGED
@@ -4,7 +4,7 @@ module Cache
|
|
4
4
|
attr_reader :store
|
5
5
|
|
6
6
|
def initialize(store)
|
7
|
-
raise "Cache Store is nil" unless store
|
7
|
+
raise "Cache Store is nil, please initialize" unless store
|
8
8
|
@store = store
|
9
9
|
end
|
10
10
|
|
@@ -32,6 +32,10 @@ module Cache
|
|
32
32
|
&block)
|
33
33
|
end
|
34
34
|
|
35
|
+
def read_multi(args)
|
36
|
+
store.read_multi(*args)
|
37
|
+
end
|
38
|
+
|
35
39
|
private
|
36
40
|
|
37
41
|
def ttl
|
data/lib/cache/object/config.rb
CHANGED
@@ -9,9 +9,8 @@ module Cache
|
|
9
9
|
|
10
10
|
def mapping_cache_keys
|
11
11
|
mappings.map do |mapping|
|
12
|
-
attributes =
|
13
|
-
|
14
|
-
memo
|
12
|
+
attributes = {}.tap do |obj|
|
13
|
+
mapping.each { |attr| obj[attr] = instance.send(attr) }
|
15
14
|
end
|
16
15
|
KeyGenerator.key_for_mapping(instance.class.name, attributes)
|
17
16
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Cache
|
2
|
+
module Object
|
3
|
+
class MultiGet
|
4
|
+
attr_reader :clazz
|
5
|
+
|
6
|
+
def initialize(clazz)
|
7
|
+
@clazz = clazz
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch_all(ids)
|
11
|
+
objs = cached_objects(ids)
|
12
|
+
remaining = missed_ids(ids, objs)
|
13
|
+
return objs if remaining.empty?
|
14
|
+
objs + load_from_db(remaining)
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_from_db(ids)
|
18
|
+
primary_key = clazz.primary_key.to_sym
|
19
|
+
clazz.where(primary_key => ids).to_a.each(&:write_cache!)
|
20
|
+
end
|
21
|
+
|
22
|
+
def object_keys(ids)
|
23
|
+
ids.map { |id| Cache::Object::KeyGenerator.key_for_object(clazz.name, id) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def cached_objects(ids)
|
27
|
+
keys = object_keys(ids)
|
28
|
+
Cache::Object.adapter.read_multi(keys).values
|
29
|
+
end
|
30
|
+
|
31
|
+
def missed_ids(ids, fetched_objects)
|
32
|
+
ids - fetched_objects.map(&:id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/cache/object/version.rb
CHANGED
@@ -58,7 +58,6 @@ RSpec.describe Cache::Object::ActiveRecord do
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
|
62
61
|
describe "caching methods" do
|
63
62
|
describe "#write_cache" do
|
64
63
|
it "calls write cache" do
|
@@ -68,7 +67,6 @@ RSpec.describe Cache::Object::ActiveRecord do
|
|
68
67
|
end
|
69
68
|
end
|
70
69
|
|
71
|
-
|
72
70
|
describe "#expire_cache" do
|
73
71
|
it "calls write cache" do
|
74
72
|
expect(adapter_instance).to receive(:delete).with(an_instance_of(Cache::Object::InstanceDecorator))
|
@@ -108,6 +106,15 @@ RSpec.describe Cache::Object::ActiveRecord do
|
|
108
106
|
end
|
109
107
|
end
|
110
108
|
|
109
|
+
describe ".fetch_all" do
|
110
|
+
it "should call through to multi_get" do
|
111
|
+
multi_getter = double(fetch_all: true)
|
112
|
+
expect(Cache::Object::MultiGet).to receive(:new).with(clazz) { multi_getter }
|
113
|
+
expect(multi_getter).to receive(:fetch_all).with([1,2,4])
|
114
|
+
clazz.fetch_all([1, 2, 4])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
111
118
|
describe "object_cache_on" do
|
112
119
|
|
113
120
|
it "creates_finder_methods" do
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Cache::Object::MultiGet do
|
4
|
+
|
5
|
+
let(:fake_clazz) { double(name: "MyObj", primary_key: :foo) }
|
6
|
+
let(:obj_arr) { 1.upto(3).map { |i| double(class: fake_clazz, id: i) } }
|
7
|
+
let(:multi_get) { Cache::Object::MultiGet.new(fake_clazz) }
|
8
|
+
let(:cache_store) { double("CacheStore", write: true) }
|
9
|
+
let(:adapter) { Cache::Object::Adapter.new(cache_store) }
|
10
|
+
|
11
|
+
describe "#object_keys" do
|
12
|
+
it "maps keys correctly" do
|
13
|
+
expect(multi_get.object_keys(1..3)).to eq(["MyObj-1", "MyObj-2", "MyObj-3"])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#cached_objects" do
|
18
|
+
it "fetches all the mapped keys" do
|
19
|
+
expect(Cache::Object).to receive(:adapter) { adapter }
|
20
|
+
expect(adapter).to receive(:read_multi).with(["MyObj-1", "MyObj-2", "MyObj-3"]) { double(values: true) }
|
21
|
+
multi_get.cached_objects(1..3)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#missed_ids" do
|
26
|
+
let(:initial_ids) { [1, 2, 3, 4, 5, 6] }
|
27
|
+
it "computes missed ids" do
|
28
|
+
expect(multi_get.missed_ids(initial_ids, obj_arr)).to eq([4, 5, 6])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#load_remaining" do
|
33
|
+
it "performs missed queries" do
|
34
|
+
expect(fake_clazz).to receive(:where).with(:foo => [1, 2, 3]).once { [double(write_cache!: true)] }
|
35
|
+
multi_get.load_from_db([1, 2, 3])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#fetch_all" do
|
40
|
+
describe "with all expected ids" do
|
41
|
+
it "never calls through to db" do
|
42
|
+
expect(multi_get).to receive(:cached_objects).with([1, 2, 3]) { obj_arr }
|
43
|
+
expect(multi_get).to receive(:load_from_db).never
|
44
|
+
multi_get.fetch_all([1, 2, 3])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "with a cache miss" do
|
49
|
+
it "calls through to db" do
|
50
|
+
expect(multi_get).to receive(:cached_objects).with([1, 2, 3]) { [ obj_arr[0] ]}
|
51
|
+
expect(multi_get).to receive(:load_from_db).with([2, 3]) { [obj_arr[1], obj_arr[2]] }
|
52
|
+
expect(multi_get.fetch_all([1, 2, 3])).to have(3).items
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -7,13 +7,15 @@ RSpec.describe "Caching" do
|
|
7
7
|
|
8
8
|
before do
|
9
9
|
CreateModelsForTest.migrate(:up)
|
10
|
+
cache = ::ActiveSupport::Cache::MemoryStore.new
|
10
11
|
Cache::Object.configure do |c|
|
11
|
-
c.cache =
|
12
|
+
c.cache = cache
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
15
16
|
after do
|
16
17
|
CreateModelsForTest.migrate(:down)
|
18
|
+
Cache::Object.instance_variable_set(:@configuration, nil)
|
17
19
|
end
|
18
20
|
|
19
21
|
let!(:user) { User.create(age: 13, name: "Bob") }
|
@@ -52,6 +54,30 @@ RSpec.describe "Caching" do
|
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
57
|
+
describe "#fetch_all" do
|
58
|
+
let!(:u1) { 1.upto(3).map { |i| User.create(age: 13, name: "name#{i}") } }
|
59
|
+
it "Should call db once for all in one read" do
|
60
|
+
|
61
|
+
expect {
|
62
|
+
User.fetch_all(u1.map(&:id))
|
63
|
+
}.to change { ActiveRecord::QueryCounter.query_count }.by(0)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "Should call the db again after cache flush" do
|
67
|
+
Cache::Object.configuration.cache.clear
|
68
|
+
|
69
|
+
expect {
|
70
|
+
User.fetch_all(u1.map(&:id))
|
71
|
+
}.to change { ActiveRecord::QueryCounter.query_count }.by(1)
|
72
|
+
|
73
|
+
# Should hit cache
|
74
|
+
expect {
|
75
|
+
User.fetch_all(u1.map(&:id))
|
76
|
+
}.to change { ActiveRecord::QueryCounter.query_count }.by(0)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
55
81
|
describe "when user id destroyed" do
|
56
82
|
it "tries to run a query" do
|
57
83
|
user.destroy
|
@@ -74,4 +100,6 @@ RSpec.describe "Caching" do
|
|
74
100
|
}.to change { ActiveRecord::QueryCounter.query_count }.by(1)
|
75
101
|
end
|
76
102
|
end
|
103
|
+
|
104
|
+
|
77
105
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
require 'cache/object'
|
2
|
+
require 'rspec/collection_matchers'
|
2
3
|
RSpec.configure do |config|
|
3
4
|
|
4
|
-
config.before do
|
5
|
+
config.before(:each) do
|
5
6
|
Cache::Object.instance_variable_set(:@configuration, nil)
|
7
|
+
Cache::Object.instance_variable_set(:@adapter, nil)
|
6
8
|
end
|
7
9
|
|
8
|
-
config.after do
|
10
|
+
config.after(:each) do
|
9
11
|
Cache::Object.instance_variable_set(:@configuration, nil)
|
12
|
+
Cache::Object.instance_variable_set(:@adapter, nil)
|
10
13
|
end
|
11
14
|
|
12
15
|
config.raise_errors_for_deprecations!
|
13
16
|
config.disable_monkey_patching!
|
14
|
-
|
15
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache-object
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Camuto
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-collection_matchers
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: guard
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,11 +153,13 @@ files:
|
|
139
153
|
- lib/cache/object/config.rb
|
140
154
|
- lib/cache/object/instance_decorator.rb
|
141
155
|
- lib/cache/object/key_generator.rb
|
156
|
+
- lib/cache/object/multi_get.rb
|
142
157
|
- lib/cache/object/version.rb
|
143
158
|
- spec/cache/object/active_record_spec.rb
|
144
159
|
- spec/cache/object/adapter_spec.rb
|
145
160
|
- spec/cache/object/config_spec.rb
|
146
161
|
- spec/cache/object/instance_decorator_spec.rb
|
162
|
+
- spec/cache/object/multi_get_spec.rb
|
147
163
|
- spec/features/cache_object_spec.rb
|
148
164
|
- spec/spec_helper.rb
|
149
165
|
- spec/support/models.rb
|
@@ -176,6 +192,7 @@ test_files:
|
|
176
192
|
- spec/cache/object/adapter_spec.rb
|
177
193
|
- spec/cache/object/config_spec.rb
|
178
194
|
- spec/cache/object/instance_decorator_spec.rb
|
195
|
+
- spec/cache/object/multi_get_spec.rb
|
179
196
|
- spec/features/cache_object_spec.rb
|
180
197
|
- spec/spec_helper.rb
|
181
198
|
- spec/support/models.rb
|