rack-cache 1.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/{COPYING → MIT-LICENSE} +0 -0
- data/README.md +95 -0
- data/lib/rack/cache/cachecontrol.rb +14 -0
- data/lib/rack/cache/context.rb +16 -3
- data/lib/rack/cache/metastore.rb +1 -1
- data/lib/rack/cache/options.rb +4 -6
- data/lib/rack/cache/response.rb +13 -6
- metadata +76 -74
- data/Gemfile +0 -2
- data/README +0 -126
- data/Rakefile +0 -139
- data/TODO +0 -27
- data/doc/configuration.markdown +0 -127
- data/doc/faq.markdown +0 -148
- data/doc/index.markdown +0 -121
- data/doc/layout.html.erb +0 -34
- data/doc/license.markdown +0 -24
- data/doc/rack-cache.css +0 -362
- data/doc/server.ru +0 -34
- data/doc/storage.markdown +0 -164
- data/example/sinatra/app.rb +0 -21
- data/example/sinatra/views/index.erb +0 -44
- data/rack-cache.gemspec +0 -75
- data/test/cache_test.rb +0 -38
- data/test/cachecontrol_test.rb +0 -145
- data/test/context_test.rb +0 -916
- data/test/entitystore_test.rb +0 -268
- data/test/key_test.rb +0 -50
- data/test/metastore_test.rb +0 -338
- data/test/options_test.rb +0 -77
- data/test/pony.jpg +0 -0
- data/test/request_test.rb +0 -19
- data/test/response_test.rb +0 -184
- data/test/spec_setup.rb +0 -232
- data/test/storage_test.rb +0 -94
data/doc/rack-cache.css
DELETED
@@ -1,362 +0,0 @@
|
|
1
|
-
/* rack-cache.css
|
2
|
-
*---------------------------------------------------------------------------
|
3
|
-
* Copyright (C) 2005-08 Ryan Tomayko <r@tomayko.com>
|
4
|
-
*/
|
5
|
-
|
6
|
-
|
7
|
-
/* 18px base font size / 25px baseline */
|
8
|
-
body {
|
9
|
-
font-size:112.5%; /* 18px (probably) */
|
10
|
-
line-height:1.3888; /* 25px */
|
11
|
-
letter-spacing:-0.02em;
|
12
|
-
margin:0 10px;
|
13
|
-
font-family: 'lucida sans unicode', 'lucida grande',
|
14
|
-
helvetica, 'bitstream vera sans', sans-serif;
|
15
|
-
color:#556;
|
16
|
-
background-color:#fff;
|
17
|
-
}
|
18
|
-
|
19
|
-
#container {
|
20
|
-
max-width:45em;
|
21
|
-
margin:0 auto;
|
22
|
-
}
|
23
|
-
|
24
|
-
h1, h2, h3 {
|
25
|
-
font-family:georgia, 'bitstream vera sans serif', 'lucida grande',
|
26
|
-
helvetica, verdana, sans-serif;
|
27
|
-
font-weight:normal;
|
28
|
-
letter-spacing:-0.05em;
|
29
|
-
color:#000;
|
30
|
-
}
|
31
|
-
i, em {
|
32
|
-
font-style:italic;
|
33
|
-
}
|
34
|
-
b, strong {
|
35
|
-
font-weight:normal;
|
36
|
-
color:#000;
|
37
|
-
}
|
38
|
-
blockquote {
|
39
|
-
color:#555;
|
40
|
-
}
|
41
|
-
blockquote em {
|
42
|
-
color:#333;
|
43
|
-
font-style:italic;
|
44
|
-
}
|
45
|
-
blockquote strong {
|
46
|
-
color:#333;
|
47
|
-
font-weight: normal;
|
48
|
-
}
|
49
|
-
dt {
|
50
|
-
font-weight:bold;
|
51
|
-
color:#000;
|
52
|
-
}
|
53
|
-
tt, pre, code, samp, kbd {
|
54
|
-
font-family: consolas, 'lucida console', 'bitstream vera sans mono',
|
55
|
-
'courier new', monospace;
|
56
|
-
color: #000;
|
57
|
-
}
|
58
|
-
pre {
|
59
|
-
color:#333;
|
60
|
-
background-color:#f9f9f9;
|
61
|
-
}
|
62
|
-
code {
|
63
|
-
color:#007A00;
|
64
|
-
}
|
65
|
-
pre code {
|
66
|
-
color:#333;
|
67
|
-
}
|
68
|
-
pre.license {
|
69
|
-
border:0;
|
70
|
-
background:#fff;
|
71
|
-
padding:0;
|
72
|
-
font-size:1.1em;
|
73
|
-
}
|
74
|
-
a, a:link {
|
75
|
-
color:#023;
|
76
|
-
background:#eef;
|
77
|
-
}
|
78
|
-
a:visited {
|
79
|
-
color:#345;
|
80
|
-
background:#fff;
|
81
|
-
}
|
82
|
-
a:hover {
|
83
|
-
background:#ccf;
|
84
|
-
color:#000;
|
85
|
-
text-decoration:none;
|
86
|
-
}
|
87
|
-
|
88
|
-
|
89
|
-
/* TYPOGRAPHY */
|
90
|
-
|
91
|
-
p, ul, ol, dl, pre, blockquote, table, form {
|
92
|
-
margin:1em 0;
|
93
|
-
}
|
94
|
-
dl {
|
95
|
-
margin-left:2em;
|
96
|
-
}
|
97
|
-
hr {
|
98
|
-
color:#eee;
|
99
|
-
background-color:#ccc;
|
100
|
-
border:0;
|
101
|
-
height:1px;
|
102
|
-
margin:1.5em 0;
|
103
|
-
}
|
104
|
-
blockquote {
|
105
|
-
font-size:0.83333em; /* 15px */
|
106
|
-
line-height:1.66666; /* 25px */
|
107
|
-
margin:1.2em 3em;
|
108
|
-
padding:0;
|
109
|
-
}
|
110
|
-
tt, pre, code, samp, kbd {
|
111
|
-
font-size: 16px;
|
112
|
-
line-height:1.1;
|
113
|
-
}
|
114
|
-
pre {
|
115
|
-
margin:1.5em 0;
|
116
|
-
padding:6px 4px 4px 6px;
|
117
|
-
border:1px solid #eee;
|
118
|
-
border-left-width:20px;
|
119
|
-
overflow:auto;
|
120
|
-
}
|
121
|
-
h1 {
|
122
|
-
font-size:2.3333em; /* 42px */
|
123
|
-
line-height:1.1904; /* 50px */
|
124
|
-
margin:0.5952em 0; /* 25px */
|
125
|
-
}
|
126
|
-
h2 {
|
127
|
-
font-size:1.66666667em; /* 30px */
|
128
|
-
line-height:1.2; /* 36px */
|
129
|
-
margin:1em 0;
|
130
|
-
}
|
131
|
-
h3 {
|
132
|
-
font-size:1.33333333em; /* 22px */
|
133
|
-
line-height:1.13636363; /* 25px */
|
134
|
-
margin:1em 0;
|
135
|
-
}
|
136
|
-
h3 code{
|
137
|
-
font-size:0.95em;
|
138
|
-
color:#000;
|
139
|
-
}
|
140
|
-
h4 {
|
141
|
-
font-size:1em;
|
142
|
-
font-weight:bold;
|
143
|
-
line-height:1.5;
|
144
|
-
margin:1em 0;
|
145
|
-
}
|
146
|
-
p small {
|
147
|
-
font-size:0.8333; /* 15px */
|
148
|
-
line-height:1.2;
|
149
|
-
}
|
150
|
-
|
151
|
-
/* Tables
|
152
|
-
--------------------------------------------------------------------------- */
|
153
|
-
|
154
|
-
table {
|
155
|
-
width:100%;
|
156
|
-
border-style:none;
|
157
|
-
border-color:#ddd;
|
158
|
-
padding:0;
|
159
|
-
}
|
160
|
-
|
161
|
-
th, td {
|
162
|
-
padding: 4px 10px 4px 5px;
|
163
|
-
border-style:solid;
|
164
|
-
border-color:#fff;
|
165
|
-
}
|
166
|
-
|
167
|
-
th {
|
168
|
-
font-weight: bold;
|
169
|
-
background: #eef;
|
170
|
-
}
|
171
|
-
|
172
|
-
td {
|
173
|
-
background: #f9f9f9;
|
174
|
-
}
|
175
|
-
|
176
|
-
tfoot {
|
177
|
-
font-style: italic;
|
178
|
-
}
|
179
|
-
|
180
|
-
caption {
|
181
|
-
background: #eee;
|
182
|
-
}
|
183
|
-
|
184
|
-
/* Header / Titling
|
185
|
-
--------------------------------------------------------------------------- */
|
186
|
-
|
187
|
-
#header {
|
188
|
-
text-align:left;
|
189
|
-
margin:1.5em auto 2em;
|
190
|
-
float:left;
|
191
|
-
width:100%;
|
192
|
-
padding-bottom:1.5em;
|
193
|
-
border-bottom:1px solid #777;
|
194
|
-
}
|
195
|
-
#header h1 {
|
196
|
-
font-family: 'lucida sans unicode', 'lucida grande',
|
197
|
-
helvetica, 'bitstream vera sans', sans-serif;
|
198
|
-
font-size:5em;
|
199
|
-
font-weight:bold;
|
200
|
-
line-height:1;
|
201
|
-
margin:0;
|
202
|
-
float:left;
|
203
|
-
color:#000;
|
204
|
-
letter-spacing:-0.08em;
|
205
|
-
}
|
206
|
-
#header h1 a, #header h1 a:link, #header h1 a:visited, #header h1 a:hover {
|
207
|
-
color:#000;
|
208
|
-
text-decoration:none;
|
209
|
-
background:transparent;
|
210
|
-
}
|
211
|
-
#header p {
|
212
|
-
margin: 0;
|
213
|
-
line-height:1.8;
|
214
|
-
color: #777;
|
215
|
-
text-transform:capitalize;
|
216
|
-
font-variant:small-caps;
|
217
|
-
float:right;
|
218
|
-
}
|
219
|
-
#header a, #header a:link, #header a:visited {
|
220
|
-
color:#445;
|
221
|
-
background:#fff;
|
222
|
-
}
|
223
|
-
#header a:hover {
|
224
|
-
background:#ccf;
|
225
|
-
color:#000;
|
226
|
-
text-decoration:none;
|
227
|
-
}
|
228
|
-
#content {
|
229
|
-
clear:both;
|
230
|
-
}
|
231
|
-
|
232
|
-
/* FOOTER */
|
233
|
-
|
234
|
-
#footer {
|
235
|
-
clear:both;
|
236
|
-
color:#555;
|
237
|
-
font-size:0.88888888em;
|
238
|
-
line-height:1.5625;
|
239
|
-
border-top:1px solid #ddd;
|
240
|
-
padding:19px 0 0 0;
|
241
|
-
margin:40px 0 20px 0;
|
242
|
-
text-align:center;
|
243
|
-
}
|
244
|
-
#footer p {
|
245
|
-
margin:0;
|
246
|
-
}
|
247
|
-
#footer form {
|
248
|
-
float:right;
|
249
|
-
}
|
250
|
-
#footer input{
|
251
|
-
font-size:10px;
|
252
|
-
}
|
253
|
-
|
254
|
-
/* MISC HELPER STYLES */
|
255
|
-
|
256
|
-
ul.clean, ol.clean {
|
257
|
-
list-style-type: none;
|
258
|
-
padding-left: 0;
|
259
|
-
}
|
260
|
-
.caps {
|
261
|
-
font-variant:small-caps;
|
262
|
-
}
|
263
|
-
.clear {
|
264
|
-
clear:both;
|
265
|
-
}
|
266
|
-
.left{
|
267
|
-
float:left;
|
268
|
-
}
|
269
|
-
.right{
|
270
|
-
float:right;
|
271
|
-
}
|
272
|
-
.center{
|
273
|
-
text-align:center;
|
274
|
-
}
|
275
|
-
.intro {
|
276
|
-
font-size:0.833333em; /* 15px */
|
277
|
-
line-height:1.666667; /* 25px */
|
278
|
-
border:1px solid #ccc;
|
279
|
-
padding:0.5em;
|
280
|
-
font-style:italic;
|
281
|
-
color:#555;
|
282
|
-
}
|
283
|
-
a.hash,
|
284
|
-
a.hash:link,
|
285
|
-
a.hash:visited {
|
286
|
-
display:block;
|
287
|
-
float:right;
|
288
|
-
background:#fff;
|
289
|
-
font-size:0.8em;
|
290
|
-
text-decoration:none;
|
291
|
-
line-height:2;
|
292
|
-
color:#999;
|
293
|
-
}
|
294
|
-
a.hash:hover {
|
295
|
-
color:MediumOrchid;
|
296
|
-
}
|
297
|
-
|
298
|
-
/* PRINT */
|
299
|
-
|
300
|
-
@media print {
|
301
|
-
html, body, #container {
|
302
|
-
margin:0;
|
303
|
-
}
|
304
|
-
#container {
|
305
|
-
width:100%;
|
306
|
-
max-width:100%;
|
307
|
-
}
|
308
|
-
#header {
|
309
|
-
margin-top:0;
|
310
|
-
}
|
311
|
-
#header p {
|
312
|
-
display:none;
|
313
|
-
}
|
314
|
-
#footer {
|
315
|
-
display:none;
|
316
|
-
}
|
317
|
-
a, a:link, a:visited {
|
318
|
-
color:#000;
|
319
|
-
background:#fff;
|
320
|
-
text-decoration:none;
|
321
|
-
}
|
322
|
-
pre.license {
|
323
|
-
font-size:0.95em;
|
324
|
-
}
|
325
|
-
@page {
|
326
|
-
size:8.5in 11in;
|
327
|
-
}
|
328
|
-
}
|
329
|
-
|
330
|
-
/* PRETTIFICATION OF SOURCE CODE */
|
331
|
-
|
332
|
-
.str { color: #181; font-style:italic; }
|
333
|
-
.kwd { color: #369; }
|
334
|
-
.com { color: #666; }
|
335
|
-
.typ { color: #c40; }
|
336
|
-
.lit { color: #900; }
|
337
|
-
.pun { color: #000; font-weight: bold; }
|
338
|
-
.pln { color: #333; }
|
339
|
-
.tag { color: #369; font-weight: bold; }
|
340
|
-
.atn { color: #939; font-weight: bold }
|
341
|
-
.atv { color: #181; }
|
342
|
-
.dec { color: #606; }
|
343
|
-
|
344
|
-
@media print {
|
345
|
-
.str { color: #060; }
|
346
|
-
.kwd { color: #006; font-weight: bold; }
|
347
|
-
.com { color: #600; font-style: italic; }
|
348
|
-
.typ { color: #404; font-weight: bold; }
|
349
|
-
.lit { color: #044; }
|
350
|
-
.pun { color: #440; }
|
351
|
-
.pln { color: #000; }
|
352
|
-
.tag { color: #006; font-weight: bold; }
|
353
|
-
.atn { color: #404; }
|
354
|
-
.atv { color: #060; }
|
355
|
-
}
|
356
|
-
|
357
|
-
/* FUCKING IE */
|
358
|
-
|
359
|
-
* html body{width:40em}
|
360
|
-
* html div.index{width:34.5em}
|
361
|
-
|
362
|
-
/* vim: set ft=css ts=4 sw=4 noexpandtab: */
|
data/doc/server.ru
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# Rackup config that serves the contents of Rack::Cache's
|
2
|
-
# doc directory. The documentation is rebuilt on each request.
|
3
|
-
|
4
|
-
# Rewrites URLs like conventional web server configs.
|
5
|
-
class Rewriter < Struct.new(:app)
|
6
|
-
def call(env)
|
7
|
-
if env['PATH_INFO'] =~ /\/$/
|
8
|
-
env['PATH_INFO'] += 'index.html'
|
9
|
-
elsif env['PATH_INFO'] !~ /\.\w+$/
|
10
|
-
env['PATH_INFO'] += '.html'
|
11
|
-
end
|
12
|
-
app.call(env)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Rebuilds documentation on each request.
|
17
|
-
class DocBuilder < Struct.new(:app)
|
18
|
-
def call(env)
|
19
|
-
if env['PATH_INFO'] !~ /\.(css|js|gif|jpg|png|ico)$/
|
20
|
-
env['rack.errors'] << "*** rebuilding documentation (rake -s doc)\n"
|
21
|
-
system "rake -s doc"
|
22
|
-
end
|
23
|
-
app.call(env)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
use Rack::CommonLogger
|
28
|
-
use DocBuilder
|
29
|
-
use Rewriter
|
30
|
-
use Rack::Static, :root => File.dirname(__FILE__), :urls => ["/"]
|
31
|
-
|
32
|
-
run(lambda{|env| [404,{},'<h1>Not Found</h1>']})
|
33
|
-
|
34
|
-
# vim: ft=ruby
|
data/doc/storage.markdown
DELETED
@@ -1,164 +0,0 @@
|
|
1
|
-
Storage
|
2
|
-
=======
|
3
|
-
|
4
|
-
__Rack::Cache__ runs within each of your backend application processes and does not
|
5
|
-
rely on a single intermediary process like most types of proxy cache
|
6
|
-
implementations. Because of this, the storage subsystem has implications on not
|
7
|
-
only where cache data is stored but whether the cache is properly distributed
|
8
|
-
between multiple backend processes. It is highly recommended that you read and
|
9
|
-
understand the following before choosing a storage implementation.
|
10
|
-
|
11
|
-
Storage Areas
|
12
|
-
-------------
|
13
|
-
|
14
|
-
__Rack::Cache__ stores cache entries in two separate configurable storage
|
15
|
-
areas: a _MetaStore_ and an _EntityStore_.
|
16
|
-
|
17
|
-
The _MetaStore_ keeps high level information about each cache entry, including
|
18
|
-
the request/response headers and other status information. When a request is
|
19
|
-
received, the core caching logic uses this meta information to determine whether
|
20
|
-
a fresh cache entry exists that can satisfy the request.
|
21
|
-
|
22
|
-
The _EntityStore_ is where the actual response body content is stored. When a
|
23
|
-
response is entered into the cache, a SHA1 digest of the response body content
|
24
|
-
is calculated and used as a key. The entries stored in the MetaStore reference
|
25
|
-
their response bodies using this SHA1 key.
|
26
|
-
|
27
|
-
Separating request/response meta-data from response content has a few important
|
28
|
-
advantages:
|
29
|
-
|
30
|
-
* Different storage types can be used for meta and entity storage. For
|
31
|
-
example, it may be desirable to use memcached to store meta information
|
32
|
-
while using the filesystem for entity storage.
|
33
|
-
|
34
|
-
* Cache entry meta-data may be retrieved quickly without also retrieving
|
35
|
-
response bodies. This avoids significant overhead when the cache misses
|
36
|
-
or only requires validation.
|
37
|
-
|
38
|
-
* Multiple different responses may include the same exact response body. In
|
39
|
-
these cases, the actual body content is stored once and referenced from
|
40
|
-
each of the meta store entries.
|
41
|
-
|
42
|
-
You should consider how the meta and entity stores differ when choosing a storage
|
43
|
-
implementation. The MetaStore does not require nearly as much memory as the
|
44
|
-
EntityStore and is accessed much more frequently. The EntityStore can grow quite
|
45
|
-
large and raw performance is less of a concern. Using a memory based storage
|
46
|
-
implementation (`heap` or `memcached`) for the MetaStore is strongly advised,
|
47
|
-
while a disk based storage implementation (`file`) is often satisfactory for
|
48
|
-
the EntityStore and uses much less memory.
|
49
|
-
|
50
|
-
Storage Configuration
|
51
|
-
---------------------
|
52
|
-
|
53
|
-
The MetaStore and EntityStore used for a particular request is determined by
|
54
|
-
inspecting the `rack-cache.metastore` and `rack-cache.entitystore` Rack env
|
55
|
-
variables. The value of these variables is a URI that identifies the storage
|
56
|
-
type and location (URI formats are documented in the following section).
|
57
|
-
|
58
|
-
The `heap:/` storage is assumed if either storage type is not explicitly
|
59
|
-
provided. This storage type has significant drawbacks for most types of
|
60
|
-
deployments so explicit configuration is advised.
|
61
|
-
|
62
|
-
The default metastore and entitystore values can be specified when the
|
63
|
-
__Rack::Cache__ object is added to the Rack middleware pipeline as follows:
|
64
|
-
|
65
|
-
use Rack::Cache,
|
66
|
-
:metastore => 'file:/var/cache/rack/meta',
|
67
|
-
:entitystore => 'file:/var/cache/rack/body'
|
68
|
-
|
69
|
-
Alternatively, the `rack-cache.metastore` and `rack-cache.entitystore`
|
70
|
-
variables may be set in the Rack environment by an upstream component.
|
71
|
-
|
72
|
-
Storage Implementations
|
73
|
-
-----------------------
|
74
|
-
|
75
|
-
__Rack::Cache__ includes meta and entity storage implementations backed by local
|
76
|
-
process memory ("heap storage"), the file system ("disk storage"), and
|
77
|
-
memcached. This section includes information on configuring __Rack::Cache__ to
|
78
|
-
use a specific storage implementation as well as pros and cons of each.
|
79
|
-
|
80
|
-
### Heap Storage
|
81
|
-
|
82
|
-
Uses local process memory to store cached entries.
|
83
|
-
|
84
|
-
use Rack::Cache,
|
85
|
-
:metastore => 'heap:/',
|
86
|
-
:entitystore => 'heap:/'
|
87
|
-
|
88
|
-
The heap storage backend is simple, fast, and mostly useless. All cache
|
89
|
-
information is stored in each backend application's local process memory (using
|
90
|
-
a normal Hash, in fact), which means that data cached under one backend is
|
91
|
-
invisible to all other backends. This leads to low cache hit rates and excessive
|
92
|
-
memory use, the magnitude of which is a function of the number of backends in
|
93
|
-
use. Further, the heap storage provides no mechanism for purging unused entries
|
94
|
-
so memory use is guaranteed to exceed that available, given enough time and
|
95
|
-
utilization.
|
96
|
-
|
97
|
-
Use of heap storage is recommended only for testing purposes or for very
|
98
|
-
simple/single-backend deployment scenarios where the number of resources served
|
99
|
-
is small and well understood.
|
100
|
-
|
101
|
-
### Disk Storage
|
102
|
-
|
103
|
-
Stores cached entries on the filesystem.
|
104
|
-
|
105
|
-
use Rack::Cache,
|
106
|
-
:metastore => 'file:/var/cache/rack/meta',
|
107
|
-
:entitystore => 'file:/var/cache/rack/body'
|
108
|
-
|
109
|
-
The URI may specify an absolute, relative, or home-rooted path:
|
110
|
-
|
111
|
-
* `file:/storage/path` - absolute path to storage directory.
|
112
|
-
* `file:storage/path` - relative path to storage directory, rooted at the
|
113
|
-
process's current working directory (`Dir.pwd`).
|
114
|
-
* `file:~user/storage/path` - path to storage directory, rooted at the
|
115
|
-
specified user's home directory.
|
116
|
-
* `file:~/storage/path` - path to storage directory, rooted at the current
|
117
|
-
user's home directory.
|
118
|
-
|
119
|
-
File system storage is simple, requires no special daemons or libraries, has a
|
120
|
-
tiny memory footprint, and allows multiple backends to share a single cache; it
|
121
|
-
is one of the slower storage implementations, however. Its use is recommended in
|
122
|
-
cases where memory is limited or in environments where more complex storage
|
123
|
-
backends (i.e., memcached) are not available. In many cases, it may be
|
124
|
-
acceptable (and even optimal) to use file system storage for the entitystore and
|
125
|
-
a more performant storage implementation (i.e. memcached) for the metastore.
|
126
|
-
|
127
|
-
__NOTE:__ When both the metastore and entitystore are configured to use file
|
128
|
-
system storage, they should be set to different paths to prevent any chance of
|
129
|
-
collision.
|
130
|
-
|
131
|
-
### Memcached Storage
|
132
|
-
|
133
|
-
Stores cached entries in a remote [memcached](http://www.danga.com/memcached/)
|
134
|
-
instance.
|
135
|
-
|
136
|
-
use Rack::Cache,
|
137
|
-
:metastore => 'memcached://localhost:11211/meta',
|
138
|
-
:entitystore => 'memcached://localhost:11211/body'
|
139
|
-
|
140
|
-
The URI must specify the host and port of a remote memcached daemon. The path
|
141
|
-
portion is an optional (but recommended) namespace that is prepended to each
|
142
|
-
cache key.
|
143
|
-
|
144
|
-
The memcached storage backend requires either the `dalli` or `memcached`
|
145
|
-
libraries. By default, the `dalli` library is used; require the `memcached`
|
146
|
-
library explicitly to use it instead.
|
147
|
-
|
148
|
-
gem install dalli
|
149
|
-
|
150
|
-
Memcached storage is reasonably fast and allows multiple backends to share a
|
151
|
-
single cache. It is also the only storage implementation that allows the cache
|
152
|
-
to reside somewhere other than the local machine. The memcached daemon stores
|
153
|
-
all data in local process memory so using it for the entitystore can result in
|
154
|
-
heavy memory usage. It is by far the best option for the metastore in
|
155
|
-
deployments with multiple backend application processes since it allows the
|
156
|
-
cache to be properly distributed and provides fast access to the
|
157
|
-
meta-information required to perform cache logic. Memcached is considerably more
|
158
|
-
complex than the other storage implementations, requiring a separate daemon
|
159
|
-
process and extra libraries. Still, its use is recommended in all cases where
|
160
|
-
you can get away with it.
|
161
|
-
|
162
|
-
[e]: http://blog.evanweaver.com/files/doc/fauna/memcached/files/README.html
|
163
|
-
[f]: http://blog.evanweaver.com/articles/2008/01/21/b-the-fastest-u-can-b-memcached/
|
164
|
-
[l]: http://tangent.org/552/libmemcached.html
|
data/example/sinatra/app.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'sinatra'
|
2
|
-
require 'rack/cache'
|
3
|
-
|
4
|
-
use Rack::Cache do
|
5
|
-
set :verbose, true
|
6
|
-
set :metastore, 'heap:/'
|
7
|
-
set :entitystore, 'heap:/'
|
8
|
-
end
|
9
|
-
|
10
|
-
before do
|
11
|
-
last_modified $updated_at ||= Time.now
|
12
|
-
end
|
13
|
-
|
14
|
-
get '/' do
|
15
|
-
erb :index
|
16
|
-
end
|
17
|
-
|
18
|
-
put '/' do
|
19
|
-
$updated_at = nil
|
20
|
-
redirect '/'
|
21
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
<html>
|
2
|
-
<head>
|
3
|
-
<title>Sample Rack::Cache Sinatra app</title>
|
4
|
-
<style type="text/css" media="screen">
|
5
|
-
body {
|
6
|
-
font-family: Georgia;
|
7
|
-
font-size: 24px;
|
8
|
-
text-align: center;
|
9
|
-
}
|
10
|
-
|
11
|
-
#headers {
|
12
|
-
font-size: 16px;
|
13
|
-
}
|
14
|
-
|
15
|
-
input {
|
16
|
-
font-size: 24px;
|
17
|
-
cursor: pointer;
|
18
|
-
}
|
19
|
-
</style>
|
20
|
-
</head>
|
21
|
-
<body>
|
22
|
-
<h1>Last updated at: <%= $updated_at.strftime('%l:%m:%S%P') %></h1>
|
23
|
-
|
24
|
-
<p>
|
25
|
-
<form action="/" method="post">
|
26
|
-
<input type="hidden" name="_method" value="PUT">
|
27
|
-
<input type="submit" value="Expire the cache.">
|
28
|
-
</form>
|
29
|
-
</p>
|
30
|
-
|
31
|
-
<div id="headers">
|
32
|
-
<h3>Headers:</h3>
|
33
|
-
|
34
|
-
<% response.headers.each do |key, value| %>
|
35
|
-
<p><%= key %>: <%= value %></p>
|
36
|
-
<% end %>
|
37
|
-
|
38
|
-
<h3>Params:</h3>
|
39
|
-
<% params.each do |key, value| %>
|
40
|
-
<p><%= key %>: <%= value || '(blank)' %></p>
|
41
|
-
<% end %>
|
42
|
-
</div>
|
43
|
-
</body>
|
44
|
-
</html>
|
data/rack-cache.gemspec
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
Gem::Specification.new do |s|
|
2
|
-
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
|
-
|
5
|
-
s.name = 'rack-cache'
|
6
|
-
s.version = '1.2'
|
7
|
-
s.date = '2012-03-05'
|
8
|
-
|
9
|
-
s.summary = "HTTP Caching for Rack"
|
10
|
-
s.description = "Rack::Cache is suitable as a quick drop-in component to enable HTTP caching for Rack-based applications that produce freshness (Expires, Cache-Control) and/or validation (Last-Modified, ETag) information."
|
11
|
-
|
12
|
-
s.authors = ["Ryan Tomayko"]
|
13
|
-
s.email = "r@tomayko.com"
|
14
|
-
|
15
|
-
# = MANIFEST =
|
16
|
-
s.files = %w[
|
17
|
-
CHANGES
|
18
|
-
COPYING
|
19
|
-
Gemfile
|
20
|
-
README
|
21
|
-
Rakefile
|
22
|
-
TODO
|
23
|
-
doc/configuration.markdown
|
24
|
-
doc/faq.markdown
|
25
|
-
doc/index.markdown
|
26
|
-
doc/layout.html.erb
|
27
|
-
doc/license.markdown
|
28
|
-
doc/rack-cache.css
|
29
|
-
doc/server.ru
|
30
|
-
doc/storage.markdown
|
31
|
-
example/sinatra/app.rb
|
32
|
-
example/sinatra/views/index.erb
|
33
|
-
lib/rack-cache.rb
|
34
|
-
lib/rack/cache.rb
|
35
|
-
lib/rack/cache/appengine.rb
|
36
|
-
lib/rack/cache/cachecontrol.rb
|
37
|
-
lib/rack/cache/context.rb
|
38
|
-
lib/rack/cache/entitystore.rb
|
39
|
-
lib/rack/cache/key.rb
|
40
|
-
lib/rack/cache/metastore.rb
|
41
|
-
lib/rack/cache/options.rb
|
42
|
-
lib/rack/cache/request.rb
|
43
|
-
lib/rack/cache/response.rb
|
44
|
-
lib/rack/cache/storage.rb
|
45
|
-
rack-cache.gemspec
|
46
|
-
test/cache_test.rb
|
47
|
-
test/cachecontrol_test.rb
|
48
|
-
test/context_test.rb
|
49
|
-
test/entitystore_test.rb
|
50
|
-
test/key_test.rb
|
51
|
-
test/metastore_test.rb
|
52
|
-
test/options_test.rb
|
53
|
-
test/pony.jpg
|
54
|
-
test/request_test.rb
|
55
|
-
test/response_test.rb
|
56
|
-
test/spec_setup.rb
|
57
|
-
test/storage_test.rb
|
58
|
-
]
|
59
|
-
# = MANIFEST =
|
60
|
-
|
61
|
-
s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
|
62
|
-
|
63
|
-
s.extra_rdoc_files = %w[README COPYING TODO CHANGES]
|
64
|
-
s.add_dependency 'rack', '>= 0.4'
|
65
|
-
|
66
|
-
s.add_development_dependency 'bacon'
|
67
|
-
s.add_development_dependency 'memcached'
|
68
|
-
s.add_development_dependency 'dalli'
|
69
|
-
|
70
|
-
s.has_rdoc = true
|
71
|
-
s.homepage = "http://tomayko.com/src/rack-cache/"
|
72
|
-
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack::Cache", "--main", "Rack::Cache"]
|
73
|
-
s.require_paths = %w[lib]
|
74
|
-
s.rubygems_version = '1.1.1'
|
75
|
-
end
|