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
- * `: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: