rack-cache 0.5 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack-cache might be problematic. Click here for more details.
- data/CHANGES +15 -0
- data/Rakefile +9 -1
- data/doc/storage.markdown +16 -14
- data/lib/rack/cache/context.rb +32 -12
- data/lib/rack/cache/entitystore.rb +18 -12
- data/lib/rack/cache/metastore.rb +21 -13
- data/lib/rack/cache/storage.rb +18 -5
- data/rack-cache.gemspec +2 -2
- data/test/context_test.rb +25 -0
- data/test/metastore_test.rb +4 -4
- data/test/options_test.rb +0 -1
- data/test/spec_setup.rb +1 -2
- metadata +5 -3
data/CHANGES
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 0.6.0 / Unreleased
|
2
|
+
|
3
|
+
* Added support for memcached clusters and other advanced
|
4
|
+
configuration provided by the memcache-client and memcached
|
5
|
+
libraries. The "metastore" and "entitystore" options can now be
|
6
|
+
set to a MemCache object or Memcached object:
|
7
|
+
|
8
|
+
memcache = MemCache.new(['127.1.1.1', '127.1.1.2'], :namespace => "/foo")
|
9
|
+
use Rack::Cache,
|
10
|
+
:metastore => memcache,
|
11
|
+
:entitystore => memcache
|
12
|
+
|
13
|
+
* Fix "memcached://" metastore URL handling. The "memcached" variation
|
14
|
+
blew up, the "memcache" version was fine.
|
15
|
+
|
1
16
|
## 0.5.0 / May 2009
|
2
17
|
|
3
18
|
* Added meta and entity store implementations based on the
|
data/Rakefile
CHANGED
@@ -110,13 +110,21 @@ file package('.tar.gz') => %w[dist/] + $spec.files do |f|
|
|
110
110
|
end
|
111
111
|
|
112
112
|
desc 'Upload gem and tar.gz distributables to rubyforge'
|
113
|
-
task :
|
113
|
+
task 'release:rubyforge' => [package('.gem'), package('.tar.gz')] do |t|
|
114
114
|
sh <<-SH
|
115
115
|
rubyforge add_release wink rack-cache #{$spec.version} #{package('.gem')} &&
|
116
116
|
rubyforge add_file wink rack-cache #{$spec.version} #{package('.tar.gz')}
|
117
117
|
SH
|
118
118
|
end
|
119
119
|
|
120
|
+
desc 'Upload gem to gemcutter.org'
|
121
|
+
task 'release:gemcutter' => [package('.gem')] do |t|
|
122
|
+
sh "gem push #{package('.gem')}"
|
123
|
+
end
|
124
|
+
|
125
|
+
desc 'Upload gem to gemcutter and rubyforge'
|
126
|
+
task 'release' => ['release:gemcutter', 'release:rubyforge']
|
127
|
+
|
120
128
|
# GEMSPEC ===================================================================
|
121
129
|
|
122
130
|
file 'rack-cache.gemspec' => FileList['{lib,test}/**','Rakefile'] do |f|
|
data/doc/storage.markdown
CHANGED
@@ -62,10 +62,9 @@ deployments so explicit configuration is advised.
|
|
62
62
|
The default metastore and entitystore values can be specified when the
|
63
63
|
__Rack::Cache__ object is added to the Rack middleware pipeline as follows:
|
64
64
|
|
65
|
-
use Rack::Cache
|
66
|
-
|
67
|
-
|
68
|
-
end
|
65
|
+
use Rack::Cache,
|
66
|
+
:metastore => 'file:/var/cache/rack/meta',
|
67
|
+
:entitystore => 'file:/var/cache/rack/body'
|
69
68
|
|
70
69
|
Alternatively, the `rack-cache.metastore` and `rack-cache.entitystore`
|
71
70
|
variables may be set in the Rack environment by an upstream component.
|
@@ -82,8 +81,9 @@ use a specific storage implementation as well as pros and cons of each.
|
|
82
81
|
|
83
82
|
Uses local process memory to store cached entries.
|
84
83
|
|
85
|
-
|
86
|
-
|
84
|
+
use Rack::Cache,
|
85
|
+
:metastore => 'heap:/',
|
86
|
+
:entitystore => 'heap:/'
|
87
87
|
|
88
88
|
The heap storage backend is simple, fast, and mostly useless. All cache
|
89
89
|
information is stored in each backend application's local process memory (using
|
@@ -102,8 +102,9 @@ is small and well understood.
|
|
102
102
|
|
103
103
|
Stores cached entries on the filesystem.
|
104
104
|
|
105
|
-
|
106
|
-
|
105
|
+
use Rack::Cache,
|
106
|
+
:metastore => 'file:/var/cache/rack/meta',
|
107
|
+
:entitystore => 'file:/var/cache/rack/body'
|
107
108
|
|
108
109
|
The URI may specify an absolute, relative, or home-rooted path:
|
109
110
|
|
@@ -132,18 +133,19 @@ collision.
|
|
132
133
|
Stores cached entries in a remote [memcached](http://www.danga.com/memcached/)
|
133
134
|
instance.
|
134
135
|
|
135
|
-
|
136
|
-
|
136
|
+
use Rack::Cache,
|
137
|
+
:metastore => 'memcached://localhost:11211/meta',
|
138
|
+
:entitystore => 'memcached://localhost:11211/body'
|
137
139
|
|
138
140
|
The URI must specify the host and port of a remote memcached daemon. The path
|
139
141
|
portion is an optional (but recommended) namespace that is prepended to each
|
140
142
|
cache key.
|
141
143
|
|
142
|
-
The memcached storage backend requires
|
143
|
-
|
144
|
-
|
144
|
+
The memcached storage backend requires either the `memcache-client` or
|
145
|
+
`memcached` libraries. By default, the `memcache-client` library is used;
|
146
|
+
require the `memcached` library explicitly to use it instead.
|
145
147
|
|
146
|
-
|
148
|
+
gem install memcache-client
|
147
149
|
|
148
150
|
Memcached storage is reasonably fast and allows multiple backends to share a
|
149
151
|
single cache. It is also the only storage implementation that allows the cache
|
data/lib/rack/cache/context.rb
CHANGED
@@ -133,8 +133,12 @@ module Rack::Cache
|
|
133
133
|
# Invalidate POST, PUT, DELETE and all methods not understood by this cache
|
134
134
|
# See RFC2616 13.10
|
135
135
|
def invalidate
|
136
|
-
record :invalidate
|
137
136
|
metastore.invalidate(@request, entitystore)
|
137
|
+
rescue Exception => e
|
138
|
+
log_error(e)
|
139
|
+
pass
|
140
|
+
else
|
141
|
+
record :invalidate
|
138
142
|
pass
|
139
143
|
end
|
140
144
|
|
@@ -147,18 +151,26 @@ module Rack::Cache
|
|
147
151
|
if @request.no_cache? && allow_reload?
|
148
152
|
record :reload
|
149
153
|
fetch
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
154
|
+
else
|
155
|
+
begin
|
156
|
+
entry = metastore.lookup(@request, entitystore)
|
157
|
+
rescue Exception => e
|
158
|
+
log_error(e)
|
159
|
+
return pass
|
160
|
+
end
|
161
|
+
if entry
|
162
|
+
if fresh_enough?(entry)
|
163
|
+
record :fresh
|
164
|
+
entry.headers['Age'] = entry.age.to_s
|
165
|
+
entry
|
166
|
+
else
|
167
|
+
record :stale
|
168
|
+
validate(entry)
|
169
|
+
end
|
155
170
|
else
|
156
|
-
record :
|
157
|
-
|
171
|
+
record :miss
|
172
|
+
fetch
|
158
173
|
end
|
159
|
-
else
|
160
|
-
record :miss
|
161
|
-
fetch
|
162
174
|
end
|
163
175
|
end
|
164
176
|
|
@@ -225,9 +237,17 @@ module Rack::Cache
|
|
225
237
|
|
226
238
|
# Write the response to the cache.
|
227
239
|
def store(response)
|
228
|
-
record :store
|
229
240
|
metastore.store(@request, response, entitystore)
|
230
241
|
response.headers['Age'] = response.age.to_s
|
242
|
+
rescue Exception => e
|
243
|
+
log_error(e)
|
244
|
+
nil
|
245
|
+
else
|
246
|
+
record :store
|
247
|
+
end
|
248
|
+
|
249
|
+
def log_error(exception)
|
250
|
+
@env['rack.errors'].write("cache error: #{exception.message}\n#{exception.backtrace.join("\n")}\n")
|
231
251
|
end
|
232
252
|
end
|
233
253
|
end
|
@@ -182,19 +182,25 @@ module Rack::Cache
|
|
182
182
|
end
|
183
183
|
|
184
184
|
def self.resolve(uri)
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
185
|
+
if uri.respond_to?(:scheme)
|
186
|
+
server = "#{uri.host}:#{uri.port || '11211'}"
|
187
|
+
options = parse_query(uri.query)
|
188
|
+
options.keys.each do |key|
|
189
|
+
value =
|
190
|
+
case value = options.delete(key)
|
191
|
+
when 'true' ; true
|
192
|
+
when 'false' ; false
|
193
|
+
else value.to_sym
|
194
|
+
end
|
195
|
+
options[k.to_sym] = value
|
196
|
+
end
|
197
|
+
options[:namespace] = uri.path.sub(/^\//, '')
|
198
|
+
new server, options
|
199
|
+
else
|
200
|
+
# if the object provided is not a URI, pass it straight through
|
201
|
+
# to the underlying implementation.
|
202
|
+
new uri
|
195
203
|
end
|
196
|
-
options[:namespace] = uri.path.sub(/^\//, '')
|
197
|
-
new server, options
|
198
204
|
end
|
199
205
|
end
|
200
206
|
|
data/lib/rack/cache/metastore.rb
CHANGED
@@ -274,19 +274,27 @@ module Rack::Cache
|
|
274
274
|
# Query parameter names and values are documented with the memcached
|
275
275
|
# library: http://tinyurl.com/4upqnd
|
276
276
|
def self.resolve(uri)
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
277
|
+
if uri.respond_to?(:scheme)
|
278
|
+
server = "#{uri.host}:#{uri.port || '11211'}"
|
279
|
+
options = parse_query(uri.query)
|
280
|
+
options.keys.each do |key|
|
281
|
+
value =
|
282
|
+
case value = options.delete(key)
|
283
|
+
when 'true' ; true
|
284
|
+
when 'false' ; false
|
285
|
+
else value.to_sym
|
286
|
+
end
|
287
|
+
options[k.to_sym] = value
|
288
|
+
end
|
289
|
+
|
290
|
+
options[:namespace] = uri.path.to_s.sub(/^\//, '')
|
291
|
+
|
292
|
+
new server, options
|
293
|
+
else
|
294
|
+
# if the object provided is not a URI, pass it straight through
|
295
|
+
# to the underlying implementation.
|
296
|
+
new uri
|
287
297
|
end
|
288
|
-
options[:namespace] = uri.path.sub(/^\//, '')
|
289
|
-
new server, options
|
290
298
|
end
|
291
299
|
end
|
292
300
|
|
@@ -359,7 +367,7 @@ module Rack::Cache
|
|
359
367
|
else
|
360
368
|
MemCache
|
361
369
|
end
|
362
|
-
MEMCACHED =
|
370
|
+
MEMCACHED = MEMCACHE
|
363
371
|
|
364
372
|
class GAEStore < MetaStore
|
365
373
|
attr_reader :cache
|
data/lib/rack/cache/storage.rb
CHANGED
@@ -30,12 +30,25 @@ module Rack::Cache
|
|
30
30
|
|
31
31
|
private
|
32
32
|
def create_store(type, uri)
|
33
|
-
uri
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
if uri.respond_to?(:scheme) || uri.respond_to?(:to_str)
|
34
|
+
uri = URI.parse(uri) unless uri.respond_to?(:scheme)
|
35
|
+
if type.const_defined?(uri.scheme.upcase)
|
36
|
+
klass = type.const_get(uri.scheme.upcase)
|
37
|
+
klass.resolve(uri)
|
38
|
+
else
|
39
|
+
fail "Unknown storage provider: #{uri.to_s}"
|
40
|
+
end
|
37
41
|
else
|
38
|
-
|
42
|
+
# hack in support for passing a MemCache or Memcached object
|
43
|
+
# as the storage URI.
|
44
|
+
case
|
45
|
+
when defined?(::MemCache) && uri.kind_of?(::MemCache)
|
46
|
+
type.const_get(:MemCache).resolve(uri)
|
47
|
+
when defined?(::Memcached) && uri.respond_to?(:stats)
|
48
|
+
type.const_get(:MemCached).resolve(uri)
|
49
|
+
else
|
50
|
+
fail "Unknown storage provider: #{uri.to_s}"
|
51
|
+
end
|
39
52
|
end
|
40
53
|
end
|
41
54
|
|
data/rack-cache.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'rack-cache'
|
6
|
-
s.version = '0.5'
|
7
|
-
s.date = '2009-
|
6
|
+
s.version = '0.5.2'
|
7
|
+
s.date = '2009-09-25'
|
8
8
|
|
9
9
|
s.description = "HTTP Caching for Rack"
|
10
10
|
s.summary = "HTTP Caching for Rack"
|
data/test/context_test.rb
CHANGED
@@ -746,4 +746,29 @@ describe 'Rack::Cache::Context' do
|
|
746
746
|
response['X-Response-Count'].should.equal '3'
|
747
747
|
end
|
748
748
|
end
|
749
|
+
|
750
|
+
it 'passes if there was a metastore exception' do
|
751
|
+
respond_with 200, 'Cache-Control' => 'max-age=10000' do |req,res|
|
752
|
+
res.body = ['Hello World']
|
753
|
+
end
|
754
|
+
|
755
|
+
get '/'
|
756
|
+
response.should.be.ok
|
757
|
+
response.body.should.equal 'Hello World'
|
758
|
+
cache.trace.should.include :store
|
759
|
+
|
760
|
+
get '/' do |cache|
|
761
|
+
cache.meta_def(:metastore) { raise Timeout::Error }
|
762
|
+
end
|
763
|
+
response.should.be.ok
|
764
|
+
response.body.should.equal 'Hello World'
|
765
|
+
cache.trace.should.include :pass
|
766
|
+
|
767
|
+
post '/' do |cache|
|
768
|
+
cache.meta_def(:metastore) { raise Timeout::Error }
|
769
|
+
end
|
770
|
+
response.should.be.ok
|
771
|
+
response.body.should.equal 'Hello World'
|
772
|
+
cache.trace.should.include :pass
|
773
|
+
end
|
749
774
|
end
|
data/test/metastore_test.rb
CHANGED
@@ -272,7 +272,7 @@ describe 'Rack::Cache::MetaStore' do
|
|
272
272
|
end
|
273
273
|
end
|
274
274
|
end
|
275
|
-
|
275
|
+
|
276
276
|
need_java 'entity store testing' do
|
277
277
|
module Rack::Cache::AppEngine
|
278
278
|
module MC
|
@@ -282,12 +282,12 @@ describe 'Rack::Cache::MetaStore' do
|
|
282
282
|
def get(key); self[key]; end;
|
283
283
|
def put(key, value, ttl = nil)
|
284
284
|
self[key] = value
|
285
|
-
end
|
285
|
+
end
|
286
286
|
|
287
287
|
end
|
288
288
|
end
|
289
289
|
end
|
290
|
-
|
290
|
+
|
291
291
|
describe 'GAEStore' do
|
292
292
|
it_should_behave_like 'A Rack::Cache::MetaStore Implementation'
|
293
293
|
before :each do
|
@@ -296,7 +296,7 @@ describe 'Rack::Cache::MetaStore' do
|
|
296
296
|
@entity_store = Rack::Cache::EntityStore::Heap.new
|
297
297
|
end
|
298
298
|
end
|
299
|
-
|
299
|
+
|
300
300
|
end
|
301
301
|
|
302
302
|
end
|
data/test/options_test.rb
CHANGED
data/test/spec_setup.rb
CHANGED
@@ -13,7 +13,7 @@ end
|
|
13
13
|
|
14
14
|
# Set the MEMCACHED environment variable as follows to enable testing
|
15
15
|
# of the MemCached meta and entity stores.
|
16
|
-
ENV['MEMCACHED'] ||= 'localhost:
|
16
|
+
ENV['MEMCACHED'] ||= 'localhost:11211'
|
17
17
|
$memcached = nil
|
18
18
|
$memcache = nil
|
19
19
|
|
@@ -70,7 +70,6 @@ def need_memcache(forwhat)
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def need_java(forwhat)
|
73
|
-
|
74
73
|
if RUBY_PLATFORM =~ /java/
|
75
74
|
yield
|
76
75
|
else
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Tomayko
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-25 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -75,6 +75,8 @@ files:
|
|
75
75
|
- test/storage_test.rb
|
76
76
|
has_rdoc: true
|
77
77
|
homepage: http://tomayko.com/src/rack-cache/
|
78
|
+
licenses: []
|
79
|
+
|
78
80
|
post_install_message:
|
79
81
|
rdoc_options:
|
80
82
|
- --line-numbers
|
@@ -100,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
102
|
requirements: []
|
101
103
|
|
102
104
|
rubyforge_project: wink
|
103
|
-
rubygems_version: 1.3.
|
105
|
+
rubygems_version: 1.3.4
|
104
106
|
signing_key:
|
105
107
|
specification_version: 2
|
106
108
|
summary: HTTP Caching for Rack
|