rtomayko-rack-cache 0.3.9 → 0.4
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 +5 -3
- data/README +18 -8
- data/Rakefile +1 -14
- data/TODO +1 -6
- data/doc/faq.markdown +8 -0
- data/doc/index.markdown +7 -7
- data/lib/rack/cache/context.rb +5 -4
- data/lib/rack/cache/options.rb +41 -36
- data/rack-cache.gemspec +2 -3
- data/test/cache_test.rb +6 -6
- data/test/context_test.rb +53 -0
- data/test/spec_setup.rb +1 -0
- metadata +2 -3
- data/doc/events.dot +0 -27
data/CHANGES
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## 0.4.0 /
|
|
1
|
+
## 0.4.0 / March 2009
|
|
2
2
|
|
|
3
3
|
* Ruby 1.9.1 / Rack 1.0 compatible.
|
|
4
4
|
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
* Implement "Cache-Control: max-age=N" request directive by forcing
|
|
11
11
|
validation when the max-age provided exceeds the age of the cache
|
|
12
|
-
entry.
|
|
12
|
+
entry. This can be disabled by setting the "allow_revalidate" option to
|
|
13
|
+
false.
|
|
13
14
|
|
|
14
15
|
* Properly implement "Cache-Control: no-cache" request directive by
|
|
15
16
|
performing a full reload. RFC 2616 states that when "no-cache" is
|
|
@@ -19,7 +20,8 @@
|
|
|
19
20
|
first validate its entry with the origin. Previously, we implemented
|
|
20
21
|
"no-cache" on requests by passing so no new cache entry would be stored
|
|
21
22
|
based on the response. Now we treat it as a forced miss and enter the
|
|
22
|
-
response into the cache if it's cacheable.
|
|
23
|
+
response into the cache if it's cacheable. This can be disabled by
|
|
24
|
+
setting the "allow_reload" option to false.
|
|
23
25
|
|
|
24
26
|
* Assume identical semantics for the "Pragma: no-cache" request header
|
|
25
27
|
as the "Cache-Control: no-cache" directive described above.
|
data/README
CHANGED
|
@@ -24,14 +24,6 @@ caching solution for small to medium sized deployments. More sophisticated /
|
|
|
24
24
|
high-performance caching systems (e.g., Varnish, Squid, httpd/mod-cache) may be
|
|
25
25
|
more appropriate for large deployments with significant throughput requirements.
|
|
26
26
|
|
|
27
|
-
Status
|
|
28
|
-
------
|
|
29
|
-
|
|
30
|
-
Rack::Cache is a young and experimental project that is likely to change
|
|
31
|
-
substantially and may not be wholly functional, consistent, fast, or correct.
|
|
32
|
-
The current focus is on reaching basic compliance with RFC 2616 and providing
|
|
33
|
-
good documentation.
|
|
34
|
-
|
|
35
27
|
Installation
|
|
36
28
|
------------
|
|
37
29
|
|
|
@@ -65,6 +57,24 @@ Assuming you've designed your backend application to take advantage of HTTP's
|
|
|
65
57
|
caching features, no further code or configuration is required for basic
|
|
66
58
|
caching.
|
|
67
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
|
+
|
|
68
78
|
Links
|
|
69
79
|
-----
|
|
70
80
|
|
data/Rakefile
CHANGED
|
@@ -31,7 +31,7 @@ end
|
|
|
31
31
|
|
|
32
32
|
# DOC =======================================================================
|
|
33
33
|
desc 'Build all documentation'
|
|
34
|
-
task :doc => %w[doc:api doc:
|
|
34
|
+
task :doc => %w[doc:api doc:markdown]
|
|
35
35
|
|
|
36
36
|
# requires the hanna gem:
|
|
37
37
|
# gem install mislav-hanna --source=http://gems.github.com
|
|
@@ -55,19 +55,6 @@ file 'doc/api/index.html' => FileList['lib/**/*.rb'] do |f|
|
|
|
55
55
|
end
|
|
56
56
|
CLEAN.include 'doc/api'
|
|
57
57
|
|
|
58
|
-
desc 'Build graphviz graphs'
|
|
59
|
-
task 'doc:graphs'
|
|
60
|
-
%w[pdf png svg].each do |filetype|
|
|
61
|
-
FileList["doc/*.dot"].each do |source|
|
|
62
|
-
dest = source.sub(/dot$/, filetype)
|
|
63
|
-
file dest => source do |f|
|
|
64
|
-
sh "dot -T#{filetype} #{source} -o #{f.name}"
|
|
65
|
-
end
|
|
66
|
-
task 'doc:graphs' => dest
|
|
67
|
-
CLEAN.include dest
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
58
|
desc 'Build markdown documentation files'
|
|
72
59
|
task 'doc:markdown'
|
|
73
60
|
FileList['doc/*.markdown'].each do |source|
|
data/TODO
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Backlog
|
|
2
2
|
|
|
3
3
|
- Move breakers.rb configuration file into rack-contrib as a middleware
|
|
4
4
|
component.
|
|
5
|
-
- Add docs on using Rack::Cache with Rails 2.3 or link to one of the
|
|
6
|
-
existing tutorials on this.
|
|
7
5
|
- Sample apps: Rack, Rails, Sinatra, Merb, etc.
|
|
8
|
-
|
|
9
|
-
## Backlog
|
|
10
|
-
|
|
11
6
|
- Use Bacon instead of test/spec
|
|
12
7
|
- Work with both memcache and memcached gems (memcached hasn't built on MacOS
|
|
13
8
|
for some time now).
|
data/doc/faq.markdown
CHANGED
|
@@ -10,6 +10,14 @@ General
|
|
|
10
10
|
-------
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
<a class='hash' id='rails' href='#rails'>#</a>
|
|
14
|
+
|
|
15
|
+
### Q: Can I use Rack::Cache with Rails?
|
|
16
|
+
|
|
17
|
+
Rack::Cache can be used with Rails 2.3 or above. Documentation and a
|
|
18
|
+
sample application is forthcoming; in the mean time, see
|
|
19
|
+
[this example of using Rack::Cache with Rails 2.3](http://snippets.aktagon.com/snippets/302-How-to-setup-and-use-Rack-Cache-with-Rails-2-3-0-RC-1).
|
|
20
|
+
|
|
13
21
|
<a class='hash' id='why-not-squid' href='#why-not-squid'>#</a>
|
|
14
22
|
|
|
15
23
|
### Q: Why Rack::Cache? Why not Squid, Varnish, Perlbol, etc.?
|
data/doc/index.markdown
CHANGED
|
@@ -9,13 +9,13 @@ for [Rack][]-based applications that produce freshness (`Expires`,
|
|
|
9
9
|
* Portable: 100% Ruby / works with any [Rack][]-enabled framework.
|
|
10
10
|
* Disk, memcached, and heap memory [storage backends][storage].
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
News
|
|
13
|
+
----
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
* [How to use Rack::Cache with Rails 2.3](http://snippets.aktagon.com/snippets/302-How-to-setup-and-use-Rack-Cache-with-Rails-2-3-0-RC-1) - it's really easy.
|
|
16
|
+
* [RailsLab's Advanced HTTP Caching Screencast](http://railslab.newrelic.com/2009/02/26/episode-11-advanced-http-caching)
|
|
17
|
+
is a really great review of HTTP caching concepts and shows how to
|
|
18
|
+
use Rack::Cache with Rails.
|
|
19
19
|
|
|
20
20
|
Installation
|
|
21
21
|
------------
|
|
@@ -51,7 +51,7 @@ caching.
|
|
|
51
51
|
More
|
|
52
52
|
----
|
|
53
53
|
|
|
54
|
-
* [Configuration
|
|
54
|
+
* [Configuration Options][config] - how to set cache options.
|
|
55
55
|
|
|
56
56
|
* [Cache Storage Documentation][storage] - detailed information on the various
|
|
57
57
|
storage implementations available in __Rack::Cache__ and how to choose the one
|
data/lib/rack/cache/context.rb
CHANGED
|
@@ -15,11 +15,12 @@ module Rack::Cache
|
|
|
15
15
|
# The Rack application object immediately downstream.
|
|
16
16
|
attr_reader :backend
|
|
17
17
|
|
|
18
|
-
def initialize(backend, options={}
|
|
18
|
+
def initialize(backend, options={})
|
|
19
19
|
@backend = backend
|
|
20
20
|
@trace = []
|
|
21
|
+
|
|
21
22
|
initialize_options options
|
|
22
|
-
|
|
23
|
+
yield self if block_given?
|
|
23
24
|
|
|
24
25
|
@private_header_keys =
|
|
25
26
|
private_headers.map { |name| "HTTP_#{name.upcase.tr('-', '_')}" }
|
|
@@ -109,7 +110,7 @@ module Rack::Cache
|
|
|
109
110
|
# Whether the cache entry is "fresh enough" to satisfy the request.
|
|
110
111
|
def fresh_enough?(entry)
|
|
111
112
|
if entry.fresh?
|
|
112
|
-
if max_age = @request.cache_control.max_age
|
|
113
|
+
if allow_revalidate? && max_age = @request.cache_control.max_age
|
|
113
114
|
max_age > 0 && max_age >= entry.age
|
|
114
115
|
else
|
|
115
116
|
true
|
|
@@ -143,7 +144,7 @@ module Rack::Cache
|
|
|
143
144
|
# stale, attempt to #validate the entry with the backend using conditional
|
|
144
145
|
# GET. When no matching cache entry is found, trigger #miss processing.
|
|
145
146
|
def lookup
|
|
146
|
-
if @request.no_cache?
|
|
147
|
+
if @request.no_cache? && allow_reload?
|
|
147
148
|
record :reload
|
|
148
149
|
fetch
|
|
149
150
|
elsif entry = metastore.lookup(@request, entitystore)
|
data/lib/rack/cache/options.rb
CHANGED
|
@@ -7,20 +7,22 @@ module Rack::Cache
|
|
|
7
7
|
# uses the Rack Environment to store option values. All options documented
|
|
8
8
|
# below are stored in the Rack Environment as "rack-cache.<option>", where
|
|
9
9
|
# <option> is the option name.
|
|
10
|
-
#
|
|
11
|
-
# The #set method can be used to configure a option values. When #set is
|
|
12
|
-
# called outside of request scope, the value applies to all requests; when
|
|
13
|
-
# called from within a request context, applies only to the request being
|
|
14
|
-
# processed.
|
|
15
10
|
module Options
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
def self.option_accessor(key)
|
|
12
|
+
name = option_name(key)
|
|
13
|
+
define_method(key) { || options[name] }
|
|
14
|
+
define_method("#{key}=") { |value| options[name] = value }
|
|
15
|
+
define_method("#{key}?") { || !! options[name] }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def option_name(key)
|
|
19
|
+
case key
|
|
20
|
+
when Symbol ; "rack-cache.#{key}"
|
|
21
|
+
when String ; key
|
|
22
|
+
else raise ArgumentError
|
|
22
23
|
end
|
|
23
24
|
end
|
|
25
|
+
module_function :option_name
|
|
24
26
|
|
|
25
27
|
# Enable verbose trace logging. This option is currently enabled by
|
|
26
28
|
# default but is likely to be disabled in a future release.
|
|
@@ -57,9 +59,9 @@ module Rack::Cache
|
|
|
57
59
|
# end
|
|
58
60
|
option_accessor :cache_key
|
|
59
61
|
|
|
60
|
-
# A URI specifying the entity-store
|
|
61
|
-
# response bodies. See the metastore option for information on
|
|
62
|
-
# schemes.
|
|
62
|
+
# A URI specifying the entity-store implementation that should be used to
|
|
63
|
+
# store response bodies. See the metastore option for information on
|
|
64
|
+
# supported URI schemes.
|
|
63
65
|
#
|
|
64
66
|
# If no entity store is specified the 'heap:/' store is assumed. This
|
|
65
67
|
# implementation has significant draw-backs so explicit configuration is
|
|
@@ -83,6 +85,16 @@ module Rack::Cache
|
|
|
83
85
|
# Default: ['Authorization', 'Cookie']
|
|
84
86
|
option_accessor :private_headers
|
|
85
87
|
|
|
88
|
+
# Specifies whether the client can force a cache reload by including a
|
|
89
|
+
# Cache-Control "no-cache" directive in the request. This is enabled by
|
|
90
|
+
# default for compliance with RFC 2616.
|
|
91
|
+
option_accessor :allow_reload
|
|
92
|
+
|
|
93
|
+
# Specifies whether the client can force a cache revalidate by including
|
|
94
|
+
# a Cache-Control "max-age=0" directive in the request. This is enabled by
|
|
95
|
+
# default for compliance with RFC 2616.
|
|
96
|
+
option_accessor :allow_revalidate
|
|
97
|
+
|
|
86
98
|
# The underlying options Hash. During initialization (or outside of a
|
|
87
99
|
# request), this is a default values Hash. During a request, this is the
|
|
88
100
|
# Rack environment Hash. The default values Hash is merged in underneath
|
|
@@ -112,6 +124,21 @@ module Rack::Cache
|
|
|
112
124
|
end
|
|
113
125
|
|
|
114
126
|
private
|
|
127
|
+
def initialize_options(options={})
|
|
128
|
+
@default_options = {
|
|
129
|
+
'rack-cache.cache_key' => Key,
|
|
130
|
+
'rack-cache.verbose' => true,
|
|
131
|
+
'rack-cache.storage' => Rack::Cache::Storage.instance,
|
|
132
|
+
'rack-cache.metastore' => 'heap:/',
|
|
133
|
+
'rack-cache.entitystore' => 'heap:/',
|
|
134
|
+
'rack-cache.default_ttl' => 0,
|
|
135
|
+
'rack-cache.private_headers' => ['Authorization', 'Cookie'],
|
|
136
|
+
'rack-cache.allow_reload' => true,
|
|
137
|
+
'rack-cache.allow_revalidate' => true
|
|
138
|
+
}
|
|
139
|
+
self.options = options
|
|
140
|
+
end
|
|
141
|
+
|
|
115
142
|
def read_option(key)
|
|
116
143
|
options[option_name(key)]
|
|
117
144
|
end
|
|
@@ -119,27 +146,5 @@ module Rack::Cache
|
|
|
119
146
|
def write_option(key, value)
|
|
120
147
|
options[option_name(key)] = value
|
|
121
148
|
end
|
|
122
|
-
|
|
123
|
-
def option_name(key)
|
|
124
|
-
case key
|
|
125
|
-
when Symbol ; "rack-cache.#{key}"
|
|
126
|
-
when String ; key
|
|
127
|
-
else raise ArgumentError
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
private
|
|
132
|
-
def initialize_options(options={})
|
|
133
|
-
@default_options = {
|
|
134
|
-
'rack-cache.cache_key' => Key,
|
|
135
|
-
'rack-cache.verbose' => true,
|
|
136
|
-
'rack-cache.storage' => Rack::Cache::Storage.instance,
|
|
137
|
-
'rack-cache.metastore' => 'heap:/',
|
|
138
|
-
'rack-cache.entitystore' => 'heap:/',
|
|
139
|
-
'rack-cache.default_ttl' => 0,
|
|
140
|
-
'rack-cache.private_headers' => ['Authorization', 'Cookie']
|
|
141
|
-
}
|
|
142
|
-
self.options = options
|
|
143
|
-
end
|
|
144
149
|
end
|
|
145
150
|
end
|
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.
|
|
7
|
-
s.date = '2009-03-
|
|
6
|
+
s.version = '0.4'
|
|
7
|
+
s.date = '2009-03-16'
|
|
8
8
|
|
|
9
9
|
s.description = "HTTP Caching for Rack"
|
|
10
10
|
s.summary = "HTTP Caching for Rack"
|
|
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
|
|
|
20
20
|
Rakefile
|
|
21
21
|
TODO
|
|
22
22
|
doc/configuration.markdown
|
|
23
|
-
doc/events.dot
|
|
24
23
|
doc/faq.markdown
|
|
25
24
|
doc/index.markdown
|
|
26
25
|
doc/layout.html.erb
|
data/test/cache_test.rb
CHANGED
|
@@ -25,14 +25,14 @@ describe 'Rack::Cache::new' do
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
it 'takes a block; executes it during initialization' do
|
|
28
|
-
state,
|
|
29
|
-
|
|
30
|
-
Rack::Cache.new @app do
|
|
31
|
-
|
|
28
|
+
state, object = 'not invoked', nil
|
|
29
|
+
instance =
|
|
30
|
+
Rack::Cache.new @app do |cache|
|
|
31
|
+
object = cache
|
|
32
32
|
state = 'invoked'
|
|
33
|
-
should.respond_to :set
|
|
33
|
+
cache.should.respond_to :set
|
|
34
34
|
end
|
|
35
35
|
state.should.equal 'invoked'
|
|
36
|
-
object.should.be
|
|
36
|
+
object.should.be instance
|
|
37
37
|
end
|
|
38
38
|
end
|
data/test/context_test.rb
CHANGED
|
@@ -148,6 +148,31 @@ describe 'Rack::Cache::Context' do
|
|
|
148
148
|
cache.trace.should.include :store
|
|
149
149
|
end
|
|
150
150
|
|
|
151
|
+
it 'does not reload responses when allow_reload is set false' do
|
|
152
|
+
count = 0
|
|
153
|
+
respond_with 200, 'Cache-Control' => 'max-age=10000' do |req,res|
|
|
154
|
+
count+= 1
|
|
155
|
+
res.body = (count == 1) ? ['Hello World'] : ['Goodbye World']
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
get '/'
|
|
159
|
+
response.should.be.ok
|
|
160
|
+
response.body.should.equal 'Hello World'
|
|
161
|
+
cache.trace.should.include :store
|
|
162
|
+
|
|
163
|
+
get '/'
|
|
164
|
+
response.should.be.ok
|
|
165
|
+
response.body.should.equal 'Hello World'
|
|
166
|
+
cache.trace.should.include :fresh
|
|
167
|
+
|
|
168
|
+
get '/',
|
|
169
|
+
'rack-cache.allow_reload' => false,
|
|
170
|
+
'HTTP_CACHE_CONTROL' => 'no-cache'
|
|
171
|
+
response.should.be.ok
|
|
172
|
+
response.body.should.equal 'Hello World'
|
|
173
|
+
cache.trace.should.not.include :reload
|
|
174
|
+
end
|
|
175
|
+
|
|
151
176
|
it 'revalidates fresh cache entry when max-age request directive is exceeded' do
|
|
152
177
|
count = 0
|
|
153
178
|
respond_with do |req,res|
|
|
@@ -175,6 +200,34 @@ describe 'Rack::Cache::Context' do
|
|
|
175
200
|
cache.trace.should.include :store
|
|
176
201
|
end
|
|
177
202
|
|
|
203
|
+
it 'does not revalidate fresh cache entry when enable_revalidate option is set false' do
|
|
204
|
+
count = 0
|
|
205
|
+
respond_with do |req,res|
|
|
206
|
+
count+= 1
|
|
207
|
+
res['Cache-Control'] = 'max-age=10000'
|
|
208
|
+
res['ETag'] = count.to_s
|
|
209
|
+
res.body = (count == 1) ? ['Hello World'] : ['Goodbye World']
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
get '/'
|
|
213
|
+
response.should.be.ok
|
|
214
|
+
response.body.should.equal 'Hello World'
|
|
215
|
+
cache.trace.should.include :store
|
|
216
|
+
|
|
217
|
+
get '/'
|
|
218
|
+
response.should.be.ok
|
|
219
|
+
response.body.should.equal 'Hello World'
|
|
220
|
+
cache.trace.should.include :fresh
|
|
221
|
+
|
|
222
|
+
get '/',
|
|
223
|
+
'rack-cache.allow_revalidate' => false,
|
|
224
|
+
'HTTP_CACHE_CONTROL' => 'max-age=0'
|
|
225
|
+
response.should.be.ok
|
|
226
|
+
response.body.should.equal 'Hello World'
|
|
227
|
+
cache.trace.should.not.include :stale
|
|
228
|
+
cache.trace.should.not.include :invalid
|
|
229
|
+
cache.trace.should.include :fresh
|
|
230
|
+
end
|
|
178
231
|
it 'fetches response from backend when cache misses' do
|
|
179
232
|
respond_with 200, 'Expires' => (Time.now + 5).httpdate
|
|
180
233
|
get '/'
|
data/test/spec_setup.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rtomayko-rack-cache
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: "0.4"
|
|
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-03-
|
|
12
|
+
date: 2009-03-16 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
@@ -40,7 +40,6 @@ files:
|
|
|
40
40
|
- Rakefile
|
|
41
41
|
- TODO
|
|
42
42
|
- doc/configuration.markdown
|
|
43
|
-
- doc/events.dot
|
|
44
43
|
- doc/faq.markdown
|
|
45
44
|
- doc/index.markdown
|
|
46
45
|
- doc/layout.html.erb
|
data/doc/events.dot
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
digraph cache_logic {
|
|
2
|
-
nodesep=1.25;
|
|
3
|
-
center=true;
|
|
4
|
-
|
|
5
|
-
node[fontname="Lucida Sans Unicode",labelloc=c,margin=0.10,0.03]
|
|
6
|
-
edge[fontname="Lucida Sans Unicode",fontcolor="#444444",labeldistance=20];
|
|
7
|
-
|
|
8
|
-
receive -> pass[label="uncacheable request",color=grey];
|
|
9
|
-
receive -> lookup[label="cacheable request"];
|
|
10
|
-
|
|
11
|
-
pass -> deliver[label="",color=grey];
|
|
12
|
-
|
|
13
|
-
lookup -> hit[label="fresh"];
|
|
14
|
-
lookup -> fetch[label="stale (needs validation)"];
|
|
15
|
-
lookup -> miss[label="uncached"];
|
|
16
|
-
|
|
17
|
-
hit -> deliver[label="sizzling"];
|
|
18
|
-
hit -> pass[label="bailing...",color=grey];
|
|
19
|
-
|
|
20
|
-
miss -> fetch[label=""];
|
|
21
|
-
miss -> pass[color=grey];
|
|
22
|
-
|
|
23
|
-
fetch -> store[label="cacheable"];
|
|
24
|
-
fetch -> deliver[label="not cacheable",color=grey];
|
|
25
|
-
|
|
26
|
-
store -> deliver[label="KTHX"];
|
|
27
|
-
}
|