tennpipes-memory 3.6.6
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.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +346 -0
- data/Rakefile +1 -0
- data/lib/tennpipes-memory.rb +125 -0
- data/lib/tennpipes-memory/helpers/cache_object.rb +23 -0
- data/lib/tennpipes-memory/helpers/cache_store.rb +16 -0
- data/lib/tennpipes-memory/helpers/fragment.rb +71 -0
- data/lib/tennpipes-memory/helpers/page.rb +169 -0
- data/test/helper.rb +24 -0
- data/test/test_moneta_store.rb +53 -0
- data/test/test_tennpipes_cache.rb +478 -0
- metadata +101 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 6aa32adf8716a8e228a1bbdde8fcb6d6e551b8ae
|
|
4
|
+
data.tar.gz: f69505b074658b20a7e246ea8a54ed7b33ac74bc
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7fa0da078e266bc68a5e96486d3537f29010e301a5c6acfda152a4283959ca44fcdbdc6e159b505716e09fbe494cb58831919ba73969c78d5a8558f42a744fed
|
|
7
|
+
data.tar.gz: 4f3b4d3ec1aeeedc9c9d63c7d8cb5c2a95d7427a2560d2e722482dbc2003985f525a3b0558f247f96510ca961714247b79cd7c76fc8d6b2f095cb692ceb99bae
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2011 Tennpipes
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
= Painless Page and Fragment Caching (tennpipes-memory)
|
|
2
|
+
|
|
3
|
+
== Overview
|
|
4
|
+
|
|
5
|
+
This component enables caching of an application's response contents on
|
|
6
|
+
both page- and fragment-levels. Output cached in this manner is
|
|
7
|
+
persisted, until it expires or is actively expired, in a configurable store
|
|
8
|
+
of your choosing. Most popular key/value stores work out of the box. Take a look
|
|
9
|
+
at the [Moneta documentation](http://rubydoc.info/gems/moneta) for a list of all supported stores.
|
|
10
|
+
|
|
11
|
+
== Caching Quickstart
|
|
12
|
+
|
|
13
|
+
Tennpipes-cache can reduce the processing load on your site very effectively
|
|
14
|
+
with minimal configuration.
|
|
15
|
+
|
|
16
|
+
By default, the component caches pages in a file store at <tt>tmp/cache</tt>
|
|
17
|
+
within your project root. Entries in this store correspond directly
|
|
18
|
+
to the request issued to your server. In other words, responses are
|
|
19
|
+
cached based on request URL, with one cache entry per URL.
|
|
20
|
+
|
|
21
|
+
This behavior is referred to as "page-level caching." If this strategy meets
|
|
22
|
+
your needs, you can enable it very easily:
|
|
23
|
+
|
|
24
|
+
# Basic, page-level caching
|
|
25
|
+
class SimpleApp < Tennpipes::Application
|
|
26
|
+
register Tennpipes::Cache
|
|
27
|
+
enable :caching
|
|
28
|
+
|
|
29
|
+
get '/foo', :cache => true do
|
|
30
|
+
expires 30 # expire cached version at least every 30 seconds
|
|
31
|
+
'Hello world'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
You can also cache on a controller-wide basis:
|
|
36
|
+
|
|
37
|
+
# Controller-wide caching example
|
|
38
|
+
class SimpleApp < Tennpipes::Application
|
|
39
|
+
register Tennpipes::Cache
|
|
40
|
+
enable :caching
|
|
41
|
+
|
|
42
|
+
get '/' do
|
|
43
|
+
'Hello world'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Requests to routes within '/admin'
|
|
47
|
+
controller '/admin', :cache => true do
|
|
48
|
+
expires 60
|
|
49
|
+
|
|
50
|
+
get '/foo' do
|
|
51
|
+
'Url is /admin/foo'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
get '/bar' do
|
|
55
|
+
'Url is /admin/bar'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
post '/baz' do # We cache only GET and HEAD request
|
|
59
|
+
'This will not be cached'
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
You can also provide a custom <tt>cache_key</tt> in any route:
|
|
65
|
+
|
|
66
|
+
class SimpleApp < Tennpipes::Application
|
|
67
|
+
register Tennpipes::Cache
|
|
68
|
+
enable :caching
|
|
69
|
+
|
|
70
|
+
get '/post/:id', :cache => true do
|
|
71
|
+
@post = Post.find(params[:id])
|
|
72
|
+
cache_key :my_name
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
In this way you can manually expire cache with CachedApp.cache.delete(:my_name)
|
|
77
|
+
for example from the Post model after an update.
|
|
78
|
+
|
|
79
|
+
If you specify <tt>:cache => true</tt> but do not invoke <tt>expires</tt>,
|
|
80
|
+
the response will be cached indefinitely. Most of the time, you will want to
|
|
81
|
+
specify the expiry of a cache entry by <tt>expires</tt>. Even a relatively
|
|
82
|
+
low value--1 or 2 seconds--can greatly increase application efficiency, especially
|
|
83
|
+
when enabled on a very active part of your domain.
|
|
84
|
+
|
|
85
|
+
== Helpers
|
|
86
|
+
|
|
87
|
+
When an application registers tennpipes-memory, it gains access to several helper
|
|
88
|
+
methods. These methods are used according to your caching strategy, so they are
|
|
89
|
+
explained here likewise--by functionality.
|
|
90
|
+
|
|
91
|
+
As with all code optimization, you may want to start simply (at "page level"),
|
|
92
|
+
and continue if necessary into sub-page (or "fragment level" ) caching. There
|
|
93
|
+
is no one way to approach caching, but it's always good to avoid complexity
|
|
94
|
+
until you need it. Start at the page level and see if it works for you.
|
|
95
|
+
|
|
96
|
+
The tennpipes-memory helpers are made available to your application thusly:
|
|
97
|
+
|
|
98
|
+
# Enable caching
|
|
99
|
+
class CachedApp < Tennpipes::Application
|
|
100
|
+
register Tennpipes::Cache # includes helpers
|
|
101
|
+
enable :caching # turns on caching
|
|
102
|
+
|
|
103
|
+
# ... controllers/routes ...
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
=== Page Caching
|
|
107
|
+
|
|
108
|
+
As described above in the "Caching Quickstart" section, page caching is very
|
|
109
|
+
easy to integrate into your application. To turn it on, simply provide the
|
|
110
|
+
<tt>:cache => true</tt> option on either a controller or one of its routes.
|
|
111
|
+
By default, cached content is persisted with a "file store"--that is, in a
|
|
112
|
+
subdirectory of your application root.
|
|
113
|
+
|
|
114
|
+
==== <tt>expires( seconds )</tt>
|
|
115
|
+
|
|
116
|
+
This helper is used within a controller or route to indicate how often cached
|
|
117
|
+
<em>page-level</em> content should persist in the cache.
|
|
118
|
+
|
|
119
|
+
After <tt>seconds</tt> seconds have passed, content previously cached will
|
|
120
|
+
be discarded and re-rendered. Code associated with that route will <em>not</em>
|
|
121
|
+
be executed; rather, its previous output will be sent to the client with a
|
|
122
|
+
200 OK status code.
|
|
123
|
+
|
|
124
|
+
# Setting content expiry time
|
|
125
|
+
class CachedApp < Tennpipes::Application
|
|
126
|
+
register Tennpipes::Cache # includes helpers
|
|
127
|
+
enable :caching # turns on caching
|
|
128
|
+
|
|
129
|
+
controller '/blog', :cache => true do
|
|
130
|
+
expires 15
|
|
131
|
+
|
|
132
|
+
get '/entries' do
|
|
133
|
+
'just broke up eating twinkies lol'
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
Note that the "latest" method call to <tt>expires</tt> determines its value: if
|
|
139
|
+
called within a route, as opposed to a controller definition, the route's
|
|
140
|
+
value will be assumed.
|
|
141
|
+
|
|
142
|
+
=== Fragment Caching
|
|
143
|
+
|
|
144
|
+
Whereas page-level caching, described in the first section of this document, works by
|
|
145
|
+
grabbing the entire output of a route, fragment caching gives the developer fine-grained
|
|
146
|
+
control of what gets cached. This type of caching occurs at whatever level you choose.
|
|
147
|
+
|
|
148
|
+
Possible uses for fragment caching might include:
|
|
149
|
+
|
|
150
|
+
* a 'feed' of some items on a page
|
|
151
|
+
* output fetched (by proxy) from an API on a third-party site
|
|
152
|
+
* parts of your page which are largely static/do not need re-rendering every request
|
|
153
|
+
* any output which is expensive to render
|
|
154
|
+
|
|
155
|
+
==== <tt>cache( key, opts, &block )</tt>
|
|
156
|
+
|
|
157
|
+
This helper is used anywhere in your application you would like to associate a fragment
|
|
158
|
+
to be cached. It can be used in within a route:
|
|
159
|
+
|
|
160
|
+
# Caching a fragment
|
|
161
|
+
class MyTweets < Tennpipes::Application
|
|
162
|
+
register Tennpipes::Cache # includes helpers
|
|
163
|
+
enable :caching # turns on caching
|
|
164
|
+
|
|
165
|
+
controller '/tweets' do
|
|
166
|
+
get :feed, :map => '/:username' do
|
|
167
|
+
username = params[:username]
|
|
168
|
+
|
|
169
|
+
@feed = cache( "feed_for_#{username}", :expires => 3 ) do
|
|
170
|
+
@tweets = Tweet.all( :username => username )
|
|
171
|
+
render 'partials/feedcontent'
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Below outputs @feed somewhere in its markup
|
|
175
|
+
render 'feeds/show'
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
This example adds a key to the cache of format <tt>feed_for_#{username}</tt> which
|
|
181
|
+
contains the contents of that user's feed. Any subsequent action within the next 3 seconds
|
|
182
|
+
will fetch the pre-rendered version of <tt>feed_for_#{username}</tt> from the cache
|
|
183
|
+
instead of re-rendering it. The rest of the page code will, however, be re-executed.
|
|
184
|
+
|
|
185
|
+
Note that any other action will reference the same content if it uses the same key:
|
|
186
|
+
|
|
187
|
+
# Multiple routes sharing the same cached fragment
|
|
188
|
+
class MyTweets < Tennpipes::Application
|
|
189
|
+
register Tennpipes::Cache # includes helpers
|
|
190
|
+
enable :caching # turns on caching
|
|
191
|
+
|
|
192
|
+
controller :tweets do
|
|
193
|
+
get :feed, :map => '/:username' do
|
|
194
|
+
username = params[:username]
|
|
195
|
+
|
|
196
|
+
@feed = cache( "feed_for_#{username}", :expires => 3 ) do
|
|
197
|
+
@tweets = Tweet.all( :username => username )
|
|
198
|
+
render 'partials/feedcontent'
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Below outputs @feed somewhere in its markup
|
|
202
|
+
render 'feeds/show'
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
get :mobile_feed, :map => '/:username.iphone' do
|
|
206
|
+
username = params[:username]
|
|
207
|
+
|
|
208
|
+
@feed = cache( "feed_for_#{username}", :expires => 3 ) do
|
|
209
|
+
@tweets = Tweet.all( :username => username )
|
|
210
|
+
render 'partials/feedcontent'
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
render 'feeds/show.iphone'
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
The <tt>opts</tt> argument is actually passed to the underlying store. The stores support the <tt>:expires</tt> option out of the box or
|
|
219
|
+
are enhanced by Moneta to support it.
|
|
220
|
+
|
|
221
|
+
Finally, to DRY up things a bit, we might do:
|
|
222
|
+
|
|
223
|
+
# Multiple routes sharing the same cached fragment
|
|
224
|
+
class MyTweets < Tennpipes::Application
|
|
225
|
+
register Tennpipes::Cache # includes helpers
|
|
226
|
+
enable :caching # turns on caching
|
|
227
|
+
|
|
228
|
+
controller :tweets do
|
|
229
|
+
# This works because all routes in this controller specify :username
|
|
230
|
+
before do
|
|
231
|
+
@feed = cache( "feed_for_#{params[:username]}", :expires => 3 ) do
|
|
232
|
+
@tweets = Tweet.all( :username => params[:username] )
|
|
233
|
+
render 'partials/feedcontent'
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
get :feed, :map => '/:username' do
|
|
238
|
+
render 'feeds/show'
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
get :mobile_feed, :map => '/:username.iphone' do
|
|
242
|
+
render 'feeds/show.iphone'
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
Of course, this example assumes the markup generated by rendering
|
|
248
|
+
<tt>partials/feedcontent</tt> would be suitable for both feed formats. This may or
|
|
249
|
+
may not be the case in your application, but the principle applies: fragments
|
|
250
|
+
are shared between all code which accesses the cache using the same key.
|
|
251
|
+
|
|
252
|
+
== Caching Store
|
|
253
|
+
|
|
254
|
+
You can set a global caching option or a per app caching options.
|
|
255
|
+
|
|
256
|
+
=== Global Caching Options
|
|
257
|
+
|
|
258
|
+
Tennpipes.cache = Tennpipes::Cache.new(:LRUHash) # default choice
|
|
259
|
+
Tennpipes.cache = Tennpipes::Cache.new(:File, :dir => Tennpipes.root('tmp', app_name.to_s, 'cache')) # Keeps cached values in file
|
|
260
|
+
Tennpipes.cache = Tennpipes::Cache.new(:Memcached) # Uses default server at localhost
|
|
261
|
+
Tennpipes.cache = Tennpipes::Cache.new(:Memcached, :server => '127.0.0.1:11211', :exception_retry_limit => 1)
|
|
262
|
+
Tennpipes.cache = Tennpipes::Cache.new(:Memcached, :backend => memcached_or_dalli_instance)
|
|
263
|
+
Tennpipes.cache = Tennpipes::Cache.new(:Redis) # Uses default server at localhost
|
|
264
|
+
Tennpipes.cache = Tennpipes::Cache.new(:Redis, :host => '127.0.0.1', :port => 6379, :db => 0)
|
|
265
|
+
Tennpipes.cache = Tennpipes::Cache.new(:Redis, :backend => redis_instance)
|
|
266
|
+
Tennpipes.cache = Tennpipes::Cache.new(:Mongo) # Uses default server at localhost
|
|
267
|
+
Tennpipes.cache = Tennpipes::Cache.new(:Mongo, :backend => mongo_client_instance)
|
|
268
|
+
|
|
269
|
+
You can manage your cache from anywhere in your app:
|
|
270
|
+
|
|
271
|
+
Tennpipes.cache['val'] = 'test'
|
|
272
|
+
Tennpipes.cache['val'] # => 'test'
|
|
273
|
+
Tennpipes.cache.delete('val')
|
|
274
|
+
Tennpipes.cache.clear
|
|
275
|
+
|
|
276
|
+
The Tennpipes cache constructor `Tennpipes::Cache.new` calls `Moneta.new` to create a cache instance. Please refer to the [Moneta documentation](http://rubydoc.info/gems/moneta) if you
|
|
277
|
+
have special requirements, for example if you want to configure the marshalling mechanism or use a more exotic backend.
|
|
278
|
+
|
|
279
|
+
==== Application Caching Options
|
|
280
|
+
|
|
281
|
+
set :cache, Tennpipes::Cache.new(:LRUHash)
|
|
282
|
+
set :cache, Tennpipes::Cache.new(:Memcached)
|
|
283
|
+
set :cache, Tennpipes::Cache.new(:Redis)
|
|
284
|
+
set :cache, Tennpipes::Cache.new(:File, :dir => Tennpipes.root('tmp', app_name.to_s, 'cache')) # default choice
|
|
285
|
+
|
|
286
|
+
You can manage your cache from anywhere in your app:
|
|
287
|
+
|
|
288
|
+
MyApp.cache['val'] = 'test'
|
|
289
|
+
MyApp.cache['val'] # => 'test'
|
|
290
|
+
MyApp.cache.delete('val')
|
|
291
|
+
MyApp.cache.clear
|
|
292
|
+
|
|
293
|
+
== Expiring Cached Content
|
|
294
|
+
|
|
295
|
+
In certain circumstances, cached content becomes stale. The <tt>expire</tt>
|
|
296
|
+
helper removes content associated with a key or keys, which your app is then
|
|
297
|
+
free to re-generate.
|
|
298
|
+
|
|
299
|
+
=== <tt>expire( *key )</tt>
|
|
300
|
+
|
|
301
|
+
==== Fragment-level expiration
|
|
302
|
+
|
|
303
|
+
Using the example above of a tweet server, let's suppose our users have a
|
|
304
|
+
tendency to post things they quickly regret. When we query our database
|
|
305
|
+
for new tweets, let's check to see if any have been deleted. If so, we'll
|
|
306
|
+
do our user a favor and instantly re-render the feed.
|
|
307
|
+
|
|
308
|
+
# Expiring fragment-level cached content
|
|
309
|
+
class MyTweets < Tennpipes::Application
|
|
310
|
+
register Tennpipes::Cache # includes helpers
|
|
311
|
+
enable :caching # turns on caching
|
|
312
|
+
enable :session # we'll use this to store last time visited
|
|
313
|
+
|
|
314
|
+
COMPANY_FOUNDING = Time.utc( 2010, "April" )
|
|
315
|
+
|
|
316
|
+
controller :tweets do
|
|
317
|
+
get :feed, :map => '/:username' do
|
|
318
|
+
last_visit = session[:last_visit] || params[:since] || COMPANY_FOUNDING
|
|
319
|
+
|
|
320
|
+
username = params[:username]
|
|
321
|
+
@tweets = Tweet.since( last_visit, :username => username ).limit( 100 )
|
|
322
|
+
|
|
323
|
+
expire( "feed since #{last_visit}" ) if @tweets.any? { |t| t.deleted_since?( last_visit ) }
|
|
324
|
+
|
|
325
|
+
session[:last_visit] = Time.now
|
|
326
|
+
@feed = cache( "feed since #{last_visit}", :expires => 60 ) do
|
|
327
|
+
@tweets = @tweets.find_all { |t| !t.deleted? }
|
|
328
|
+
render 'partials/feedcontent'
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
render 'feeds/show'
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
Normally, this example will only re-cache feed content every 60 seconds,
|
|
337
|
+
but it will do so immediately if any tweets have been deleted.
|
|
338
|
+
|
|
339
|
+
==== Page-level expiration
|
|
340
|
+
|
|
341
|
+
Page-level expiration works exactly like the example above--by using
|
|
342
|
+
<tt>expire</tt> in your controller. The key is typically <tt>env['PATH_INFO']</tt>.
|
|
343
|
+
|
|
344
|
+
== Copyright
|
|
345
|
+
|
|
346
|
+
Copyright (c) 2011-2013 Tennpipes. See LICENSE for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../gem_rake_helper')
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'fileutils' unless defined?(FileUtils)
|
|
2
|
+
require 'tennpipes-base'
|
|
3
|
+
require 'tennpipes-helper'
|
|
4
|
+
FileSet.glob_require('tennpipes-memory/{helpers}/*.rb', __FILE__)
|
|
5
|
+
require 'moneta'
|
|
6
|
+
|
|
7
|
+
module Tennpipes
|
|
8
|
+
class << self
|
|
9
|
+
##
|
|
10
|
+
# Returns the caching engine.
|
|
11
|
+
#
|
|
12
|
+
# @example
|
|
13
|
+
# # with: Tennpipes.cache = Tennpipes::Cache.new(:File, :dir => /my/cache/path)
|
|
14
|
+
# Tennpipes.cache['val'] = 'test'
|
|
15
|
+
# Tennpipes.cache['val'] # => 'test'
|
|
16
|
+
# Tennpipes.cache.delete('val')
|
|
17
|
+
# Tennpipes.cache.clear
|
|
18
|
+
#
|
|
19
|
+
def cache
|
|
20
|
+
@_cache
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Set the caching engine.
|
|
25
|
+
#
|
|
26
|
+
# @param value
|
|
27
|
+
# Instance of Moneta store
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:LRUHash) # default choice
|
|
31
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:File, :dir => Tennpipes.root('tmp', app_name.to_s, 'cache')) # Keeps cached values in file
|
|
32
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:Memcached) # Uses default server at localhost
|
|
33
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:Memcached, :server => '127.0.0.1:11211', :exception_retry_limit => 1)
|
|
34
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:Memcached, :backend => memcached_or_dalli_instance)
|
|
35
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:Redis) # Uses default server at localhost
|
|
36
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:Redis, :host => '127.0.0.1', :port => 6379, :db => 0)
|
|
37
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:Redis, :backend => redis_instance)
|
|
38
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:Mongo) # Uses default server at localhost
|
|
39
|
+
# Tennpipes.cache = Tennpipes::Cache.new(:Mongo, :backend => mongo_client_instance)
|
|
40
|
+
#
|
|
41
|
+
# # You can manage your cache from anywhere in your app:
|
|
42
|
+
#
|
|
43
|
+
# Tennpipes.cache['val'] = 'test'
|
|
44
|
+
# Tennpipes.cache['val'] # => 'test'
|
|
45
|
+
# Tennpipes.cache.delete('val')
|
|
46
|
+
# Tennpipes.cache.clear
|
|
47
|
+
#
|
|
48
|
+
def cache=(value)
|
|
49
|
+
@_cache= value
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# This component enables caching of an application's response contents on
|
|
55
|
+
# both page- and fragment-levels. Output cached in this manner is
|
|
56
|
+
# persisted, until it expires or is actively expired, in a configurable store
|
|
57
|
+
# of your choosing. Several common caching stores are supported out of the box.
|
|
58
|
+
#
|
|
59
|
+
module Cache
|
|
60
|
+
class << self
|
|
61
|
+
##
|
|
62
|
+
# Register these helpers:
|
|
63
|
+
#
|
|
64
|
+
# Tennpipes::Cache::Helpers::ObjectCache
|
|
65
|
+
# Tennpipes::Cache::Helpers::CacheStore
|
|
66
|
+
# Tennpipes::Cache::Helpers::Fragment
|
|
67
|
+
# Tennpipes::Cache::Helpers::Page
|
|
68
|
+
#
|
|
69
|
+
# for Tennpipes::Application.
|
|
70
|
+
#
|
|
71
|
+
# By default we use FileStore as showed below:
|
|
72
|
+
#
|
|
73
|
+
# set :cache, Tennpipes::Cache.new(:File, :dir => Tennpipes.root('tmp', app_name.to_s, 'cache'))
|
|
74
|
+
#
|
|
75
|
+
# However, you can also change the file store easily in your app.rb:
|
|
76
|
+
#
|
|
77
|
+
# set :cache, Tennpipes::Cache.new(:LRUHash) # Keeps cached values in memory
|
|
78
|
+
# set :cache, Tennpipes::Cache.new(:Memcached) # Uses default server at localhost
|
|
79
|
+
# set :cache, Tennpipes::Cache.new(:Memcached, '127.0.0.1:11211', :exception_retry_limit => 1)
|
|
80
|
+
# set :cache, Tennpipes::Cache.new(:Memcached, :backend => memcached_or_dalli_instance)
|
|
81
|
+
# set :cache, Tennpipes::Cache.new(:Redis) # Uses default server at localhost
|
|
82
|
+
# set :cache, Tennpipes::Cache.new(:Redis, :host => '127.0.0.1', :port => 6379, :db => 0)
|
|
83
|
+
# set :cache, Tennpipes::Cache.new(:Redis, :backend => redis_instance)
|
|
84
|
+
# set :cache, Tennpipes::Cache.new(:Mongo) # Uses default server at localhost
|
|
85
|
+
# set :cache, Tennpipes::Cache.new(:Mongo, :backend => mongo_client_instance)
|
|
86
|
+
# set :cache, Tennpipes::Cache.new(:File, :dir => Tennpipes.root('tmp', app_name.to_s, 'cache')) # default choice
|
|
87
|
+
#
|
|
88
|
+
# You can manage your cache from anywhere in your app:
|
|
89
|
+
#
|
|
90
|
+
# MyApp.cache['val'] = 'test'
|
|
91
|
+
# MyApp.cache['val'] # => 'test'
|
|
92
|
+
# MyApp.cache.delete('val')
|
|
93
|
+
# MyApp.cache.clear
|
|
94
|
+
#
|
|
95
|
+
def registered(app)
|
|
96
|
+
app.helpers Tennpipes::Cache::Helpers::ObjectCache
|
|
97
|
+
app.helpers Tennpipes::Cache::Helpers::CacheStore
|
|
98
|
+
app.helpers Tennpipes::Cache::Helpers::Fragment
|
|
99
|
+
app.helpers Tennpipes::Cache::Helpers::Page
|
|
100
|
+
unless app.respond_to?(:cache)
|
|
101
|
+
cache_dir = Tennpipes.root('tmp', defined?(app.app_name) ? app.app_name.to_s : '', 'cache')
|
|
102
|
+
app.set :cache, Tennpipes::Cache.new(:File, :dir => cache_dir)
|
|
103
|
+
end
|
|
104
|
+
app.disable :caching unless app.respond_to?(:caching)
|
|
105
|
+
included(app)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def included(base)
|
|
109
|
+
base.extend Tennpipes::Cache::Helpers::Page::ClassMethods
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def tennpipes_route_added(route, verb, path, args, options, block)
|
|
113
|
+
Tennpipes::Cache::Helpers::Page.tennpipes_route_added(route, verb, path, args, options, block)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.new(name, options = {})
|
|
118
|
+
# Activate expiration by default
|
|
119
|
+
options[:expires] = true unless options.include?(:expires)
|
|
120
|
+
Moneta.new(name, options)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
Tennpipes.cache = Tennpipes::Cache.new(:LRUHash)
|
|
124
|
+
end
|
|
125
|
+
end
|