josh-rack-cache 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|