josh-rack-cache 0.5.1
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/CHANGES +167 -0
- data/COPYING +18 -0
- data/README +110 -0
- data/Rakefile +137 -0
- data/TODO +27 -0
- data/doc/configuration.markdown +112 -0
- data/doc/faq.markdown +141 -0
- data/doc/index.markdown +121 -0
- data/doc/layout.html.erb +34 -0
- data/doc/license.markdown +24 -0
- data/doc/rack-cache.css +362 -0
- data/doc/server.ru +34 -0
- data/doc/storage.markdown +164 -0
- data/example/sinatra/app.rb +25 -0
- data/example/sinatra/views/index.erb +44 -0
- data/lib/rack/cache.rb +45 -0
- data/lib/rack/cache/appengine.rb +52 -0
- data/lib/rack/cache/cachecontrol.rb +193 -0
- data/lib/rack/cache/context.rb +253 -0
- data/lib/rack/cache/entitystore.rb +339 -0
- data/lib/rack/cache/key.rb +52 -0
- data/lib/rack/cache/metastore.rb +407 -0
- data/lib/rack/cache/options.rb +150 -0
- data/lib/rack/cache/request.rb +33 -0
- data/lib/rack/cache/response.rb +267 -0
- data/lib/rack/cache/storage.rb +62 -0
- data/rack-cache.gemspec +70 -0
- data/test/cache_test.rb +38 -0
- data/test/cachecontrol_test.rb +139 -0
- data/test/context_test.rb +774 -0
- data/test/entitystore_test.rb +230 -0
- data/test/key_test.rb +50 -0
- data/test/metastore_test.rb +302 -0
- data/test/options_test.rb +77 -0
- data/test/pony.jpg +0 -0
- data/test/request_test.rb +19 -0
- data/test/response_test.rb +178 -0
- data/test/spec_setup.rb +237 -0
- data/test/storage_test.rb +94 -0
- metadata +118 -0
data/CHANGES
ADDED
@@ -0,0 +1,167 @@
|
|
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
|
+
|
16
|
+
## 0.5.0 / May 2009
|
17
|
+
|
18
|
+
* Added meta and entity store implementations based on the
|
19
|
+
memcache-client library. These are the default unless the memcached
|
20
|
+
library has already been required.
|
21
|
+
|
22
|
+
* The "allow_reload" and "allow_revalidate" options now default to
|
23
|
+
false instead of true. This means we break with RFC 2616 out of
|
24
|
+
the box but this is the expected configuration in a huge majority
|
25
|
+
of gateway cache scenarios. See the docs on configuration
|
26
|
+
options for more information on these options:
|
27
|
+
http://tomayko.com/src/rack-cache/configuration
|
28
|
+
|
29
|
+
* Added Google AppEngine memcache entity store and metastore
|
30
|
+
implementations. To use GAE's memcache with rack-cache, set the
|
31
|
+
"metastore" and "entitystore" options as follows:
|
32
|
+
|
33
|
+
use Rack::Cache,
|
34
|
+
:metastore => 'gae://cache-meta',
|
35
|
+
:entitystore => 'gae://cache-body'
|
36
|
+
|
37
|
+
The 'cache-meta' and 'cache-body' parts are memcache namespace
|
38
|
+
prefixes and should be set to different values.
|
39
|
+
|
40
|
+
## 0.4.0 / March 2009
|
41
|
+
|
42
|
+
* Ruby 1.9.1 / Rack 1.0 compatible.
|
43
|
+
|
44
|
+
* Invalidate cache entries that match the request URL on non-GET/HEAD
|
45
|
+
requests. i.e., POST, PUT, DELETE cause matching cache entries to
|
46
|
+
be invalidated. The cache entry is validated with the backend using
|
47
|
+
a conditional GET the next time it's requested.
|
48
|
+
|
49
|
+
* Implement "Cache-Control: max-age=N" request directive by forcing
|
50
|
+
validation when the max-age provided exceeds the age of the cache
|
51
|
+
entry. This can be disabled by setting the "allow_revalidate" option to
|
52
|
+
false.
|
53
|
+
|
54
|
+
* Properly implement "Cache-Control: no-cache" request directive by
|
55
|
+
performing a full reload. RFC 2616 states that when "no-cache" is
|
56
|
+
present in the request, the cache MUST NOT serve a stored response even
|
57
|
+
after successful validation. This is slightly different from the
|
58
|
+
"no-cache" directive in responses, which indicates that the cache must
|
59
|
+
first validate its entry with the origin. Previously, we implemented
|
60
|
+
"no-cache" on requests by passing so no new cache entry would be stored
|
61
|
+
based on the response. Now we treat it as a forced miss and enter the
|
62
|
+
response into the cache if it's cacheable. This can be disabled by
|
63
|
+
setting the "allow_reload" option to false.
|
64
|
+
|
65
|
+
* Assume identical semantics for the "Pragma: no-cache" request header
|
66
|
+
as the "Cache-Control: no-cache" directive described above.
|
67
|
+
|
68
|
+
* Less crazy logging. When the verbose option is set, a single log entry
|
69
|
+
is written with a comma separated list of trace events. For example, if
|
70
|
+
the cache was stale but validated, the following log entry would be
|
71
|
+
written: "cache: stale, valid, store". When the verbose option is false,
|
72
|
+
no logging occurs.
|
73
|
+
|
74
|
+
* Added "X-Rack-Cache" response header with the same comma separated trace
|
75
|
+
value as described above. This gives some visibility into how the cache
|
76
|
+
processed the request.
|
77
|
+
|
78
|
+
* Add support for canonicalized cache keys, as well as custom cache key
|
79
|
+
generators, which are specified in the options as :cache_key as either
|
80
|
+
any object that has a call() or as a block. Cache key generators get
|
81
|
+
passed a request object and return a cache key string.
|
82
|
+
|
83
|
+
## 0.3.0 / December 2008
|
84
|
+
|
85
|
+
* Add support for public and private cache control directives. Responses
|
86
|
+
marked as explicitly public are cached even when the request includes
|
87
|
+
an Authorization or Cookie header. Responses marked as explicitly private
|
88
|
+
are considered uncacheable.
|
89
|
+
|
90
|
+
* Added a "private_headers" option that dictates which request headers
|
91
|
+
trigger default "private" cache control processing. By default, the
|
92
|
+
Cookie and Authorization headers are included. Headers may be added or
|
93
|
+
removed as necessary to change the default private logic.
|
94
|
+
|
95
|
+
* Adhere to must-revalidate/proxy-revalidate cache control directives by
|
96
|
+
not assigning the default_ttl to responses that don't include freshness
|
97
|
+
information. This should let us begin using default_ttl more liberally
|
98
|
+
since we can control it using the must-revalidate/proxy-revalidate directives.
|
99
|
+
|
100
|
+
* Use the s-maxage Cache-Control value in preference to max-age when
|
101
|
+
present. The ttl= method now sets the s-maxage value instead of max-age.
|
102
|
+
Code that used ttl= to control freshness at the client needs to change
|
103
|
+
to set the max-age directive explicitly.
|
104
|
+
|
105
|
+
* Enable support for X-Sendfile middleware by responding to #to_path on
|
106
|
+
bodies served from disk storage. Adding the Rack::Sendfile component
|
107
|
+
upstream from Rack::Cache will result in cached bodies being served
|
108
|
+
directly by the web server (instead of being read in Ruby).
|
109
|
+
|
110
|
+
* BUG: MetaStore hits but EntityStore misses. This would 500 previously; now
|
111
|
+
we detect it and act as if the MetaStore missed as well.
|
112
|
+
|
113
|
+
* Implement low level #purge method on all concrete entity store
|
114
|
+
classes -- removes the entity body corresponding to the SHA1 key
|
115
|
+
provided and returns nil.
|
116
|
+
|
117
|
+
* Basically sane handling of HEAD requests. A HEAD request is never passed
|
118
|
+
through to the backend except when transitioning with pass!. This means
|
119
|
+
that the cache responds to HEAD requests without invoking the backend at
|
120
|
+
all when the cached entry is fresh. When no cache entry exists, or the
|
121
|
+
cached entry is stale and can be validated, the backend is invoked with
|
122
|
+
a GET request and the HEAD is handled right before the response
|
123
|
+
is delivered upstream.
|
124
|
+
|
125
|
+
* BUG: The Age response header was not being set properly when a stale
|
126
|
+
entry was validated. This would result in Age values that exceeded
|
127
|
+
the freshness lifetime in responses.
|
128
|
+
|
129
|
+
* BUG: A cached entry in a heap meta store could be unintentionally
|
130
|
+
modified by request processing since the cached objects were being
|
131
|
+
returned directly. The result was typically missing/incorrect header
|
132
|
+
values (e.g., missing Content-Type header). [dkubb]
|
133
|
+
|
134
|
+
* BUG: 304 responses should not include entity headers (especially
|
135
|
+
Content-Length). This is causing Safari/WebKit weirdness on 304
|
136
|
+
responses.
|
137
|
+
|
138
|
+
* BUG: The If-None-Match header was being ignored, causing the cache
|
139
|
+
to send 200 responses to matching conditional GET requests.
|
140
|
+
|
141
|
+
## 0.2.0 / 2008-10-24 / Initial Release
|
142
|
+
|
143
|
+
* Document events and transitions in `rack/cache/config/default.rb`
|
144
|
+
* Basic logging support (`trace`, `warn`, `info`, `error` from within Context)
|
145
|
+
* EntityStore: store entity bodies keyed by SHA
|
146
|
+
* MetaStore: store response headers keyed by URL
|
147
|
+
* Last-Modified/ETag validation
|
148
|
+
* Vary support
|
149
|
+
* Implement error! transition
|
150
|
+
* New Rack::Cache::Core
|
151
|
+
* memcached meta and entity store implementations
|
152
|
+
* URI based storage configuration
|
153
|
+
* Read options from Rack env if present (rack-cache.XXX keys)
|
154
|
+
* `object` is now `entry`
|
155
|
+
* Documentation framework and website
|
156
|
+
* Document storage areas and implementations
|
157
|
+
* Document configuration/events
|
158
|
+
|
159
|
+
## 0.1.0 / 2008-07-21 / Proof of concept (unreleased)
|
160
|
+
|
161
|
+
* Basic core with event support
|
162
|
+
* `#import` method for bringing in config files
|
163
|
+
* Freshness based expiration
|
164
|
+
* RFC 2616 If-Modified-Since based validation
|
165
|
+
* A horribly shitty storage back-end (Hash in mem)
|
166
|
+
* Don't cache hop-by-hop headers: Connection, Keep-Alive, Proxy-Authenticate,
|
167
|
+
Proxy-Authorization, TE, Trailers, Transfer-Encoding, Upgrade
|
data/COPYING
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2008 Ryan Tomayko <http://tomayko.com/about>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
Rack::Cache
|
2
|
+
===========
|
3
|
+
|
4
|
+
Rack::Cache is suitable as a quick drop-in component to enable HTTP caching for
|
5
|
+
Rack-based applications that produce freshness (Expires, Cache-Control) and/or
|
6
|
+
validation (Last-Modified, ETag) information:
|
7
|
+
|
8
|
+
* Standards-based (RFC 2616)
|
9
|
+
* Freshness/expiration based caching
|
10
|
+
* Validation (If-Modified-Since / If-None-Match)
|
11
|
+
* Vary support
|
12
|
+
* Cache-Control: public, private, max-age, s-maxage, must-revalidate,
|
13
|
+
and proxy-revalidate.
|
14
|
+
* Portable: 100% Ruby / works with any Rack-enabled framework
|
15
|
+
* Disk, memcached, and heap memory storage backends
|
16
|
+
|
17
|
+
For more information about Rack::Cache features and usage, see:
|
18
|
+
|
19
|
+
http://tomayko.com/src/rack-cache/
|
20
|
+
|
21
|
+
Rack::Cache is not overly optimized for performance. The main goal of the
|
22
|
+
project is to provide a portable, easy-to-configure, and standards-based
|
23
|
+
caching solution for small to medium sized deployments. More sophisticated /
|
24
|
+
high-performance caching systems (e.g., Varnish, Squid, httpd/mod-cache) may be
|
25
|
+
more appropriate for large deployments with significant throughput requirements.
|
26
|
+
|
27
|
+
Installation
|
28
|
+
------------
|
29
|
+
|
30
|
+
From Gem:
|
31
|
+
|
32
|
+
$ sudo gem install rack-cache
|
33
|
+
|
34
|
+
With a local working copy:
|
35
|
+
|
36
|
+
$ git clone git://github.com/rtomayko/rack-cache.git
|
37
|
+
$ rake package && sudo rake install
|
38
|
+
|
39
|
+
Basic Usage
|
40
|
+
-----------
|
41
|
+
|
42
|
+
Rack::Cache is implemented as a piece of Rack middleware and can be used with
|
43
|
+
any Rack-based application. If your application includes a rackup (`.ru`) file
|
44
|
+
or uses Rack::Builder to construct the application pipeline, simply require
|
45
|
+
and use as follows:
|
46
|
+
|
47
|
+
require 'rack/cache'
|
48
|
+
|
49
|
+
use Rack::Cache,
|
50
|
+
:metastore => 'file:/var/cache/rack/meta',
|
51
|
+
:entitystore => 'file:/var/cache/rack/body',
|
52
|
+
:verbose => true
|
53
|
+
|
54
|
+
run app
|
55
|
+
|
56
|
+
Assuming you've designed your backend application to take advantage of HTTP's
|
57
|
+
caching features, no further code or configuration is required for basic
|
58
|
+
caching.
|
59
|
+
|
60
|
+
Using with Rails
|
61
|
+
----------------
|
62
|
+
|
63
|
+
Add this to your `config/environment.rb`:
|
64
|
+
|
65
|
+
config.middleware.use Rack::Cache,
|
66
|
+
:verbose => true,
|
67
|
+
:metastore => 'file:/var/cache/rack/meta',
|
68
|
+
:entitystore => 'file:/var/cache/rack/body'
|
69
|
+
|
70
|
+
You should now see `Rack::Cache` listed in the middleware pipeline:
|
71
|
+
|
72
|
+
rake middleware
|
73
|
+
|
74
|
+
See the following for more information:
|
75
|
+
|
76
|
+
http://snippets.aktagon.com/snippets/302
|
77
|
+
|
78
|
+
Links
|
79
|
+
-----
|
80
|
+
|
81
|
+
Documentation:
|
82
|
+
http://tomayko.com/src/rack-cache/
|
83
|
+
|
84
|
+
Mailing List:
|
85
|
+
http://groups.google.com/group/rack-cache
|
86
|
+
|
87
|
+
GitHub:
|
88
|
+
http://github.com/rtomayko/rack-cache/
|
89
|
+
|
90
|
+
License
|
91
|
+
-------
|
92
|
+
|
93
|
+
Copyright (c) 2008 Ryan Tomayko <http://tomayko.com/about>
|
94
|
+
|
95
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
96
|
+
of this software and associated documentation files (the "Software"), to
|
97
|
+
deal in the Software without restriction, including without limitation the
|
98
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
99
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
100
|
+
furnished to do so, subject to the following conditions:
|
101
|
+
|
102
|
+
The above copyright notice and this permission notice shall be included in
|
103
|
+
all copies or substantial portions of the Software.
|
104
|
+
|
105
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
106
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
107
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
108
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
109
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
110
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
|
3
|
+
task :default => :test
|
4
|
+
|
5
|
+
CLEAN.include %w[coverage/ doc/api tags]
|
6
|
+
CLOBBER.include %w[dist]
|
7
|
+
|
8
|
+
# load gemspec like github's gem builder to surface any SAFE issues.
|
9
|
+
Thread.new do
|
10
|
+
require 'rubygems/specification'
|
11
|
+
$spec = eval("$SAFE=3\n#{File.read('rack-cache.gemspec')}")
|
12
|
+
end.join
|
13
|
+
|
14
|
+
# SPECS =====================================================================
|
15
|
+
|
16
|
+
desc 'Run specs with story style output'
|
17
|
+
task :spec do
|
18
|
+
sh 'specrb --specdox -Ilib:test test/*_test.rb'
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Run specs with unit test style output'
|
22
|
+
task :test => FileList['test/*_test.rb'] do |t|
|
23
|
+
suite = t.prerequisites
|
24
|
+
sh "specrb -Ilib:test #{suite.join(' ')}", :verbose => false
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Generate test coverage report'
|
28
|
+
task :rcov do
|
29
|
+
sh "rcov -Ilib:test test/*_test.rb"
|
30
|
+
end
|
31
|
+
|
32
|
+
# DOC =======================================================================
|
33
|
+
desc 'Build all documentation'
|
34
|
+
task :doc => %w[doc:api doc:markdown]
|
35
|
+
|
36
|
+
# requires the hanna gem:
|
37
|
+
# gem install mislav-hanna --source=http://gems.github.com
|
38
|
+
desc 'Build API documentation (doc/api)'
|
39
|
+
task 'doc:api' => 'doc/api/index.html'
|
40
|
+
file 'doc/api/index.html' => FileList['lib/**/*.rb'] do |f|
|
41
|
+
rm_rf 'doc/api'
|
42
|
+
sh((<<-SH).gsub(/[\s\n]+/, ' ').strip)
|
43
|
+
hanna
|
44
|
+
--op doc/api
|
45
|
+
--promiscuous
|
46
|
+
--charset utf8
|
47
|
+
--fmt html
|
48
|
+
--inline-source
|
49
|
+
--line-numbers
|
50
|
+
--accessor option_accessor=RW
|
51
|
+
--main Rack::Cache
|
52
|
+
--title 'Rack::Cache API Documentation'
|
53
|
+
#{f.prerequisites.join(' ')}
|
54
|
+
SH
|
55
|
+
end
|
56
|
+
CLEAN.include 'doc/api'
|
57
|
+
|
58
|
+
desc 'Build markdown documentation files'
|
59
|
+
task 'doc:markdown'
|
60
|
+
FileList['doc/*.markdown'].each do |source|
|
61
|
+
dest = "doc/#{File.basename(source, '.markdown')}.html"
|
62
|
+
file dest => [source, 'doc/layout.html.erb'] do |f|
|
63
|
+
puts "markdown: #{source} -> #{dest}" if verbose
|
64
|
+
require 'erb' unless defined? ERB
|
65
|
+
require 'rdiscount' unless defined? RDiscount
|
66
|
+
template = File.read(source)
|
67
|
+
content = Markdown.new(ERB.new(template, 0, "%<>").result(binding), :smart).to_html
|
68
|
+
title = content.match("<h1>(.*)</h1>")[1] rescue ''
|
69
|
+
layout = ERB.new(File.read("doc/layout.html.erb"), 0, "%<>")
|
70
|
+
output = layout.result(binding)
|
71
|
+
File.open(dest, 'w') { |io| io.write(output) }
|
72
|
+
end
|
73
|
+
task 'doc:markdown' => dest
|
74
|
+
CLEAN.include dest
|
75
|
+
end
|
76
|
+
|
77
|
+
desc 'Publish documentation'
|
78
|
+
task 'doc:publish' => :doc do
|
79
|
+
sh 'rsync -avz doc/ gus@tomayko.com:/src/rack-cache'
|
80
|
+
end
|
81
|
+
|
82
|
+
desc 'Start the documentation development server (requires thin)'
|
83
|
+
task 'doc:server' do
|
84
|
+
sh 'cd doc && thin --rackup server.ru --port 3035 start'
|
85
|
+
end
|
86
|
+
|
87
|
+
# PACKAGING =================================================================
|
88
|
+
|
89
|
+
def package(ext='')
|
90
|
+
"dist/rack-cache-#{$spec.version}" + ext
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'Build packages'
|
94
|
+
task :package => %w[.gem .tar.gz].map {|e| package(e)}
|
95
|
+
|
96
|
+
desc 'Build and install as local gem'
|
97
|
+
task :install => package('.gem') do
|
98
|
+
sh "gem install #{package('.gem')}"
|
99
|
+
end
|
100
|
+
|
101
|
+
directory 'dist/'
|
102
|
+
|
103
|
+
file package('.gem') => %w[dist/ rack-cache.gemspec] + $spec.files do |f|
|
104
|
+
sh "gem build rack-cache.gemspec"
|
105
|
+
mv File.basename(f.name), f.name
|
106
|
+
end
|
107
|
+
|
108
|
+
file package('.tar.gz') => %w[dist/] + $spec.files do |f|
|
109
|
+
sh "git archive --format=tar HEAD | gzip > #{f.name}"
|
110
|
+
end
|
111
|
+
|
112
|
+
desc 'Upload gem and tar.gz distributables to rubyforge'
|
113
|
+
task :release => [package('.gem'), package('.tar.gz')] do |t|
|
114
|
+
sh <<-SH
|
115
|
+
rubyforge add_release wink rack-cache #{$spec.version} #{package('.gem')} &&
|
116
|
+
rubyforge add_file wink rack-cache #{$spec.version} #{package('.tar.gz')}
|
117
|
+
SH
|
118
|
+
end
|
119
|
+
|
120
|
+
# GEMSPEC ===================================================================
|
121
|
+
|
122
|
+
file 'rack-cache.gemspec' => FileList['{lib,test}/**','Rakefile'] do |f|
|
123
|
+
# read spec file and split out manifest section
|
124
|
+
spec = File.read(f.name)
|
125
|
+
parts = spec.split(" # = MANIFEST =\n")
|
126
|
+
fail 'bad spec' if parts.length != 3
|
127
|
+
# determine file list from git ls-files
|
128
|
+
files = `git ls-files`.
|
129
|
+
split("\n").sort.reject{ |file| file =~ /^\./ }.
|
130
|
+
map{ |file| " #{file}" }.join("\n")
|
131
|
+
# piece file back together and write...
|
132
|
+
parts[1] = " s.files = %w[\n#{files}\n ]\n"
|
133
|
+
spec = parts.join(" # = MANIFEST =\n")
|
134
|
+
spec.sub!(/s.date = '.*'/, "s.date = '#{Time.now.strftime("%Y-%m-%d")}'")
|
135
|
+
File.open(f.name, 'w') { |io| io.write(spec) }
|
136
|
+
puts "updated #{f.name}"
|
137
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
## 0.5
|
2
|
+
|
3
|
+
- Document allow_revalidate and allow_reload options.
|
4
|
+
- Support multiple memcache servers.
|
5
|
+
- Purge/invalidate everything
|
6
|
+
- Explicit expiration/invalidation based on response headers or via an
|
7
|
+
object interface passed in the rack env.
|
8
|
+
- Sample apps: Rack, Rails, Sinatra, Merb, etc.
|
9
|
+
- Move old breakers.rb configuration file into rack-contrib as a
|
10
|
+
middleware component.
|
11
|
+
|
12
|
+
## Backlog
|
13
|
+
|
14
|
+
- Use Bacon instead of test/spec
|
15
|
+
- Fast path pass processing. We do a lot more than necessary just to determine
|
16
|
+
that the response should be passed through untouched.
|
17
|
+
- Invalidate at the URI of the Location or Content-Location response header
|
18
|
+
on POST, PUT, or DELETE that results in a redirect.
|
19
|
+
- Maximum size of cached entity
|
20
|
+
- Last-Modified factor: requests that have a Last-Modified header but no Expires
|
21
|
+
header have a TTL assigned based on the last modified age of the response:
|
22
|
+
TTL = (Age * Factor), or, 1h = (10h * 0.1)
|
23
|
+
- Consider implementing ESI (http://www.w3.org/TR/esi-lang). This should
|
24
|
+
probably be implemented as a separate middleware component.
|
25
|
+
- stale-while-revalidate
|
26
|
+
- Serve cached copies when down (see: stale-if-error) - e.g., database
|
27
|
+
connection drops and the cache takes over what it can.
|