cached_resource 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
- * `:collection_synchronize` Use collections to generate cache entries for individuals. Update the existing cached principal collection with new individuals. Default: `false`
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, :enabled => false
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.ttl)
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
- end
45
- end
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
@@ -1,3 +1,3 @@
1
1
  module CachedResource
2
- VERSION = "2.2.0"
2
+ VERSION = "2.3.0"
3
3
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe CachedResource do
4
4
 
5
- before(:all) do
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(:all) do
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 cache" do
114
- Foo.cached_resource.cache.should == Bar.cached_resource.cache
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
- cr = Foo.cached_resource
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.2.0
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-08 00:00:00.000000000 Z
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: !ruby/object:Gem::Requirement
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: !ruby/object:Gem::Requirement
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: !ruby/object:Gem::Requirement
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: !ruby/object:Gem::Requirement
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: !ruby/object:Gem::Requirement
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.21
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: