cached_resource 2.2.0 → 2.3.0
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.
data/README.md
CHANGED
@@ -8,14 +8,12 @@ CachedResource is a Ruby gem whose goal is to increase the performance of intera
|
|
8
8
|
CachedResource has been tested with the following Ruby versions:
|
9
9
|
|
10
10
|
* 1.8.7
|
11
|
-
* 1.9.2
|
12
|
-
* 1.9.3
|
11
|
+
* 1.9.2, 1.9.3
|
13
12
|
|
14
13
|
CachedResource is designed to be framework agnostic, but will hook into Rails for caching and logging. If there is a `Rails.cache` and/or a `Rails.logger`, then it _should_ be OK. It is known to work with the following Rails versions:
|
15
14
|
|
16
15
|
* 3.1.3
|
17
|
-
* 3.2.2
|
18
|
-
* 3.2.3
|
16
|
+
* 3.2.2, 3.2.3
|
19
17
|
|
20
18
|
## Configuration
|
21
19
|
**Set up CachedResource across all ActiveResources:**
|
@@ -35,14 +33,16 @@ CachedResource accepts the following options:
|
|
35
33
|
|
36
34
|
* `:enabled` Default: `true`
|
37
35
|
* `:ttl` The time in seconds until the cache should expire. Default: `604800`
|
38
|
-
* `:
|
36
|
+
* `:ttl_randomization` Enable ttl randomization. Default: `false`
|
37
|
+
* `:ttl_randomization_scale` A Range from which a random value will be selected to scale the ttl. Default: `1..2`
|
38
|
+
* `:collection_synchronize` Use collections to generate cache entries for individuals. Update the existing cached principal collection when retrieving subsets of the principal collection or individuals. Default: `false`
|
39
39
|
* `:collection_arguments` The arguments that identify the principal collection request. Default: `[:all]`
|
40
40
|
* `:logger` The logger to which CachedResource messages should be written. Default: The `Rails.logger` if available, or an `ActiveSupport::BufferedLogger`
|
41
41
|
* `:cache` The cache store that CacheResource should use. Default: The `Rails.cache` if available, or an `ActiveSupport::Cache::MemoryStore`
|
42
42
|
|
43
43
|
You can set them like this:
|
44
44
|
|
45
|
-
cached_resource :cache => MyCacheStore.new, :ttl => 60, :collection_synchronize => true, :logger => MyLogger.new
|
45
|
+
cached_resource :cache => MyCacheStore.new, :ttl => 60, :collection_synchronize => true, :logger => MyLogger.new
|
46
46
|
|
47
47
|
You can also change them on the fly.
|
48
48
|
|
@@ -58,11 +58,19 @@ Set the cache expiry time to 60 seconds.
|
|
58
58
|
|
59
59
|
MyActiveResource.cached_resource.ttl = 60
|
60
60
|
|
61
|
+
Enable cache expiry time randomization, allowing it to fall randomly between 60 and 120 seconds.
|
62
|
+
|
63
|
+
MyActiveResource.cached_resource.ttl_randomization = true
|
64
|
+
|
65
|
+
Change the cache expiry time randomization scale so that the cache expiry time falls randomly between 30 and 180 seconds.
|
66
|
+
|
67
|
+
MyActiveResource.cached_resource.ttl_randomization_scale = 0.5..3
|
68
|
+
|
61
69
|
Enable collection synchronization. This will cause a call to `MyActiveResource.all` to also create cache entries for each of its members. So, for example, a later call to `MyActiveResource.find(1)` will be read from the cache instead of requested from the remote service.
|
62
70
|
|
63
71
|
MyActiveResource.cached_resource.collection_synchronize = true
|
64
72
|
|
65
|
-
Change the arguments that identify the principal collection request. If for some reason you are concerned with a collection that is retrieved at a non-standard URL, you may specify the Ruby arguments that produce that URL. When `collection_synchronize` is `true`, the collection returned from a request that matches these arguments will be cached and later updated when one of its members is retrieved.
|
73
|
+
Change the arguments that identify the principal collection request. If for some reason you are concerned with a collection that is retrieved at a "non-standard" URL, you may specify the Ruby arguments that produce that URL. When `collection_synchronize` is `true`, the collection returned from a request that matches these arguments will be cached and later updated when one of its members or a subset is retrieved.
|
66
74
|
|
67
75
|
MyActiveResource.cached_resource.collection_arguments = [:all, :params => {:name => "Bob"}]
|
68
76
|
|
@@ -104,7 +112,6 @@ Feedback is greatly appreciated! Check out this project's [issue tracker](https:
|
|
104
112
|
This may change at any time.
|
105
113
|
|
106
114
|
* Callbacks on before and after reload
|
107
|
-
* Cache expiry randomization
|
108
115
|
* Consider checksums to improve the determination of freshness/changédness
|
109
116
|
|
110
117
|
|
@@ -92,7 +92,7 @@ module CachedResource
|
|
92
92
|
# The key is processed to make sure it is valid.
|
93
93
|
def cache_write(key, object)
|
94
94
|
key = cache_key(Array(key)) unless key.is_a? String
|
95
|
-
result = cached_resource.cache.write(key, object, :expires_in => cached_resource.
|
95
|
+
result = cached_resource.cache.write(key, object, :expires_in => cached_resource.generate_ttl)
|
96
96
|
result && cached_resource.logger.info("#{CachedResource::Configuration::LOGGER_PREFIX} WRITE #{key}")
|
97
97
|
result
|
98
98
|
end
|
@@ -16,6 +16,8 @@ module CachedResource
|
|
16
16
|
# defaults. The following options exist for cached resource:
|
17
17
|
# :enabled, default: true
|
18
18
|
# :ttl, default: 604800
|
19
|
+
# :ttl_randomization, default: false,
|
20
|
+
# :ttl_randomization_scale, default: 1..2,
|
19
21
|
# :collection_synchronize, default: false,
|
20
22
|
# :collection_arguments, default: [:all]
|
21
23
|
# :cache, default: Rails.cache or ActiveSupport::Cache::MemoryStore.new,
|
@@ -24,6 +26,8 @@ module CachedResource
|
|
24
26
|
super({
|
25
27
|
:enabled => true,
|
26
28
|
:ttl => 604800,
|
29
|
+
:ttl_randomization => false,
|
30
|
+
:ttl_randomization_scale => 1..2,
|
27
31
|
:collection_synchronize => false,
|
28
32
|
:collection_arguments => [:all],
|
29
33
|
:cache => defined?(Rails.cache) && Rails.cache || CACHE,
|
@@ -31,6 +35,13 @@ module CachedResource
|
|
31
35
|
}.merge(options))
|
32
36
|
end
|
33
37
|
|
38
|
+
# Determine the time until a cache entry should expire. If ttl_randomization
|
39
|
+
# is enabled, then a the set ttl will be multiplied by a random
|
40
|
+
# value from ttl_randomization_scale.
|
41
|
+
def generate_ttl
|
42
|
+
ttl_randomization && randomized_ttl || ttl
|
43
|
+
end
|
44
|
+
|
34
45
|
# Enables caching.
|
35
46
|
def on!
|
36
47
|
self.enabled = true
|
@@ -41,6 +52,20 @@ module CachedResource
|
|
41
52
|
self.enabled = false
|
42
53
|
end
|
43
54
|
|
44
|
-
|
45
|
-
|
55
|
+
private
|
56
|
+
|
57
|
+
# Get a randomized ttl value between ttl * ttl_randomization_scale begin
|
58
|
+
# and ttl * ttl_randomization_scale end
|
59
|
+
def randomized_ttl
|
60
|
+
ttl * sample_range(ttl_randomization_scale)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Choose a random value from within the given range, optionally
|
64
|
+
# seeded by seed.
|
65
|
+
def sample_range(range, seed=nil)
|
66
|
+
srand seed if seed
|
67
|
+
rand * (range.end - range.begin) + range.begin
|
68
|
+
end
|
46
69
|
|
70
|
+
end
|
71
|
+
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe CachedResource do
|
4
4
|
|
5
|
-
before(:
|
5
|
+
before(:each) do
|
6
6
|
class Thing < ActiveResource::Base
|
7
7
|
self.site = "http://api.thing.com"
|
8
8
|
cached_resource
|
@@ -17,7 +17,7 @@ describe CachedResource do
|
|
17
17
|
@other_thing_json = @other_thing.to_json
|
18
18
|
end
|
19
19
|
|
20
|
-
after(:
|
20
|
+
after(:each) do
|
21
21
|
Thing.cached_resource.cache.clear
|
22
22
|
Object.send(:remove_const, :Thing)
|
23
23
|
end
|
@@ -229,6 +229,27 @@ describe CachedResource do
|
|
229
229
|
Thing.cached_resource.cache.read("thing/all")[0].name.should_not == result.name
|
230
230
|
end
|
231
231
|
end
|
232
|
+
|
233
|
+
describe "when ttl randomization is enabled" do
|
234
|
+
before(:each) do
|
235
|
+
@ttl = 1
|
236
|
+
Thing.cached_resource.ttl = @ttl
|
237
|
+
Thing.cached_resource.ttl_randomization = true
|
238
|
+
Thing.cached_resource.send(:sample_range, 1..2, @ttl)
|
239
|
+
# next ttl 1.72032449344216
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should generate a random ttl" do
|
243
|
+
Thing.cached_resource.cache.should_receive(:write)
|
244
|
+
Thing.cached_resource.cache.stub(:write) do |key, value, options|
|
245
|
+
# we know the ttl should not be the same as the set ttl
|
246
|
+
options[:expires_in].should_not == @ttl
|
247
|
+
end
|
248
|
+
|
249
|
+
Thing.find(1)
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
232
253
|
end
|
233
254
|
|
234
255
|
describe "when disabled" do
|
@@ -110,22 +110,8 @@ describe "CachedResource::Configuration" do
|
|
110
110
|
Foo.cached_resource.object_id.should_not == Bar.cached_resource.object_id
|
111
111
|
end
|
112
112
|
|
113
|
-
it "they should have the same
|
114
|
-
Foo.cached_resource.
|
115
|
-
Foo.cached_resource.cache.object_id.should == Bar.cached_resource.cache.object_id
|
116
|
-
end
|
117
|
-
|
118
|
-
it "they should have the same ttl" do
|
119
|
-
Foo.cached_resource.ttl.should == Bar.cached_resource.ttl
|
120
|
-
end
|
121
|
-
|
122
|
-
it "they should have the same logger" do
|
123
|
-
Foo.cached_resource.logger.should == Bar.cached_resource.logger
|
124
|
-
Foo.cached_resource.logger.object_id.should == Bar.cached_resource.logger.object_id
|
125
|
-
end
|
126
|
-
|
127
|
-
it "they should have the same enablement" do
|
128
|
-
Foo.cached_resource.enabled.should == Bar.cached_resource.enabled
|
113
|
+
it "they should have the same attributes" do
|
114
|
+
Foo.cached_resource.instance_variable_get(:@table).should == Bar.cached_resource.instance_variable_get(:@table)
|
129
115
|
end
|
130
116
|
|
131
117
|
end
|
@@ -181,8 +167,7 @@ describe "CachedResource::Configuration" do
|
|
181
167
|
end
|
182
168
|
|
183
169
|
it "should have the specified options" do
|
184
|
-
|
185
|
-
cr.ttl.should == 60
|
170
|
+
Foo.cached_resource.ttl.should == 60
|
186
171
|
end
|
187
172
|
|
188
173
|
it "should have the default options for anything unspecified" do
|
@@ -193,8 +178,42 @@ describe "CachedResource::Configuration" do
|
|
193
178
|
cr.collection_synchronize.should == false
|
194
179
|
cr.collection_arguments.should == [:all]
|
195
180
|
cr.custom.should == nil
|
181
|
+
cr.ttl_randomization.should == false
|
182
|
+
cr.ttl_randomization_scale.should == (1..2)
|
196
183
|
end
|
197
184
|
|
198
185
|
end
|
199
186
|
|
187
|
+
# At the moment, not too keen on implementing some fancy
|
188
|
+
# randomness validator.
|
189
|
+
describe "when ttl randomization is enabled" do
|
190
|
+
before(:each) do
|
191
|
+
@ttl = 1
|
192
|
+
configuration.ttl = @ttl
|
193
|
+
configuration.ttl_randomization = true
|
194
|
+
configuration.send(:sample_range, 1..2, @ttl)
|
195
|
+
# next ttl: 1.72032449344216
|
196
|
+
end
|
197
|
+
|
198
|
+
it "it should produce a random ttl between ttl and ttl * 2" do
|
199
|
+
generated_ttl = configuration.generate_ttl
|
200
|
+
generated_ttl.should_not == 10
|
201
|
+
(@ttl..(2 * @ttl)).should include(generated_ttl)
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "when a ttl randomization scale is set" do
|
205
|
+
before(:each) do
|
206
|
+
@lower = 0.5
|
207
|
+
@upper = 1
|
208
|
+
configuration.ttl_randomization_scale = @lower..@upper
|
209
|
+
# next ttl 0.860162246721079
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should produce a random ttl between ttl * lower bound and ttl * upper bound" do
|
213
|
+
lower = @ttl * @lower
|
214
|
+
upper = @ttl * @upper
|
215
|
+
(lower..upper).should include(configuration.generate_ttl)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
200
219
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cached_resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70156223360120 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,15 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0'
|
24
|
+
version_requirements: *70156223360120
|
30
25
|
- !ruby/object:Gem::Dependency
|
31
26
|
name: activeresource
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
27
|
+
requirement: &70156223383920 !ruby/object:Gem::Requirement
|
33
28
|
none: false
|
34
29
|
requirements:
|
35
30
|
- - ! '>='
|
@@ -37,15 +32,10 @@ dependencies:
|
|
37
32
|
version: '0'
|
38
33
|
type: :runtime
|
39
34
|
prerelease: false
|
40
|
-
version_requirements:
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '0'
|
35
|
+
version_requirements: *70156223383920
|
46
36
|
- !ruby/object:Gem::Dependency
|
47
37
|
name: activesupport
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirement: &70156223383060 !ruby/object:Gem::Requirement
|
49
39
|
none: false
|
50
40
|
requirements:
|
51
41
|
- - ! '>='
|
@@ -53,15 +43,10 @@ dependencies:
|
|
53
43
|
version: '0'
|
54
44
|
type: :runtime
|
55
45
|
prerelease: false
|
56
|
-
version_requirements:
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ! '>='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
46
|
+
version_requirements: *70156223383060
|
62
47
|
- !ruby/object:Gem::Dependency
|
63
48
|
name: nilio
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirement: &70156223382540 !ruby/object:Gem::Requirement
|
65
50
|
none: false
|
66
51
|
requirements:
|
67
52
|
- - ! '>='
|
@@ -69,15 +54,10 @@ dependencies:
|
|
69
54
|
version: '0'
|
70
55
|
type: :runtime
|
71
56
|
prerelease: false
|
72
|
-
version_requirements:
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ! '>='
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0'
|
57
|
+
version_requirements: *70156223382540
|
78
58
|
- !ruby/object:Gem::Dependency
|
79
59
|
name: rspec
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirement: &70156223382020 !ruby/object:Gem::Requirement
|
81
61
|
none: false
|
82
62
|
requirements:
|
83
63
|
- - ! '>='
|
@@ -85,12 +65,7 @@ dependencies:
|
|
85
65
|
version: '0'
|
86
66
|
type: :development
|
87
67
|
prerelease: false
|
88
|
-
version_requirements:
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
68
|
+
version_requirements: *70156223382020
|
94
69
|
description: Enables request-based caching for ActiveResource
|
95
70
|
email: email@suspi.net
|
96
71
|
executables: []
|
@@ -133,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
108
|
version: '0'
|
134
109
|
requirements: []
|
135
110
|
rubyforge_project:
|
136
|
-
rubygems_version: 1.8.
|
111
|
+
rubygems_version: 1.8.15
|
137
112
|
signing_key:
|
138
113
|
specification_version: 3
|
139
114
|
summary: Caching for ActiveResource
|
@@ -141,4 +116,3 @@ test_files:
|
|
141
116
|
- spec/cached_resource/caching_spec.rb
|
142
117
|
- spec/cached_resource/configuration_spec.rb
|
143
118
|
- spec/spec_helper.rb
|
144
|
-
has_rdoc:
|