cache_fu 0.1.5 → 0.2.0.pre0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +12 -11
- data/README +6 -3
- data/lib/acts_as_cached/benchmarking.rb +18 -47
- data/lib/acts_as_cached/cache_methods.rb +17 -66
- data/lib/acts_as_cached/railtie.rb +7 -5
- data/lib/cache_fu.rb +11 -25
- metadata +4 -11
- data/defaults/extensions.rb.default +0 -40
- data/defaults/memcached.yml.default +0 -32
- data/defaults/memcached_ctl.default +0 -81
- data/lib/acts_as_cached/config.rb +0 -106
- data/lib/acts_as_cached/disabled.rb +0 -30
- data/lib/acts_as_cached/recipes.rb +0 -8
- data/lib/tasks/memcached.rake +0 -59
data/LICENSE
CHANGED
@@ -1,18 +1,19 @@
|
|
1
|
+
Copyright (c) 2011 Kreeti Technologies
|
1
2
|
Copyright (c) 2007 Chris Wanstrath
|
2
3
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
-
this software and associated documentation files (the "Software"), to deal in
|
5
|
-
the Software without restriction, including without limitation the rights to
|
6
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
7
|
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
5
|
+
this software and associated documentation files (the "Software"), to deal in
|
6
|
+
the Software without restriction, including without limitation the rights to
|
7
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
8
9
|
subject to the following conditions:
|
9
10
|
|
10
|
-
The above copyright notice and this permission notice shall be included in all
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
11
12
|
copies or substantial portions of the Software.
|
12
13
|
|
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, FITNESS
|
15
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
16
|
-
COPYRIGHT HOLDERS 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
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
16
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
17
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
19
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
CHANGED
@@ -3,7 +3,11 @@
|
|
3
3
|
A rewrite of acts_as_cached.
|
4
4
|
This version is only compatible with rails 3 and above.
|
5
5
|
|
6
|
-
|
6
|
+
This gem version uses Dalli.
|
7
|
+
If you want a memcache compatible version then see the branch memcache_client or use version 0.1.5 of the gem.
|
8
|
+
|
9
|
+
For fragment and page caching use Rails DalliStore as it already provides all the functionality.
|
10
|
+
|
7
11
|
This gem is very useful for caching in models.
|
8
12
|
|
9
13
|
== Changes from acts_as_cached 1
|
@@ -17,5 +21,4 @@ This gem is very useful for caching in models.
|
|
17
21
|
- set_cache on an instance can take a ttl
|
18
22
|
>> @story.set_cache(15.days)
|
19
23
|
|
20
|
-
|
21
|
-
Chris Wanstrath [ chris[at]ozmm[dot]org ]
|
24
|
+
Surendra Singhi [ ssinghi[at]kreeti[dot]com]
|
@@ -2,62 +2,33 @@ require 'benchmark'
|
|
2
2
|
|
3
3
|
module ActsAsCached
|
4
4
|
module Benchmarking #:nodoc:
|
5
|
-
def self.
|
6
|
-
|
5
|
+
def self.runtime=(value)
|
6
|
+
Thread.current['memcache_runtime'] = value
|
7
7
|
end
|
8
8
|
|
9
|
-
def self.
|
10
|
-
|
9
|
+
def self.runtime
|
10
|
+
Thread.current['memcache_runtime'] ||= 0.0
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
seconds = Benchmark.realtime {
|
18
|
-
result = use_silence ? ActionController::Base.silence { yield } : yield
|
19
|
-
}
|
20
|
-
|
21
|
-
@@cache_runtime ||= 0.0
|
22
|
-
@@cache_runtime += seconds
|
23
|
-
|
24
|
-
logger.add(log_level, "==> #{title} (#{'%.5f' % seconds})")
|
25
|
-
result
|
26
|
-
end
|
27
|
-
|
28
|
-
def fetch_cache_with_benchmarking(*args)
|
29
|
-
cache_benchmark "Got #{cache_key args.first} from cache." do
|
30
|
-
fetch_cache_without_benchmarking(*args)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def set_cache_with_benchmarking(*args)
|
35
|
-
cache_benchmark "Set #{cache_key args.first} to cache." do
|
36
|
-
set_cache_without_benchmarking(*args)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def expire_cache_with_benchmarking(*args)
|
41
|
-
cache_benchmark "Deleted #{cache_key args.first} from cache." do
|
42
|
-
expire_cache_without_benchmarking(*args)
|
43
|
-
end
|
13
|
+
def self.reset_runtime
|
14
|
+
rt, self.runtime = runtime, 0
|
15
|
+
rt
|
44
16
|
end
|
45
17
|
|
46
|
-
def self.
|
47
|
-
|
48
|
-
|
18
|
+
def self.benchmark(event)
|
19
|
+
self.runtime += event.duration
|
20
|
+
return unless Rails.logger && Rails.logger.debug?
|
49
21
|
|
50
|
-
|
51
|
-
alias_method_chain :fetch_cache, :benchmarking
|
52
|
-
alias_method_chain :set_cache, :benchmarking
|
53
|
-
alias_method_chain :expire_cache, :benchmarking
|
54
|
-
|
55
|
-
def logger; Rails.logger end unless respond_to? :logger
|
56
|
-
end
|
22
|
+
Rails.logger.debug("Cache #{event.name.sub('cache_','').sub('.active_support','')} ==> #{event.payload[:key]} (#{'%.1fms' % event.duration}) #{'HIT' if event.payload[:hit]}#{'MISS' if event.payload[:miss]}")
|
57
23
|
end
|
58
24
|
end
|
59
25
|
end
|
60
26
|
|
27
|
+
ActiveSupport::Notifications.subscribe /cache/ do |*args|
|
28
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
29
|
+
ActsAsCached::Benchmarking.benchmark(event)
|
30
|
+
end
|
31
|
+
|
61
32
|
module ActsAsCached
|
62
33
|
module MemcacheRuntime
|
63
34
|
extend ActiveSupport::Concern
|
@@ -65,8 +36,8 @@ module ActsAsCached
|
|
65
36
|
|
66
37
|
def append_info_to_payload(payload)
|
67
38
|
super
|
68
|
-
payload[:memcache_runtime] = ActsAsCached::Benchmarking.
|
69
|
-
ActsAsCached::Benchmarking.
|
39
|
+
payload[:memcache_runtime] = ActsAsCached::Benchmarking.runtime
|
40
|
+
ActsAsCached::Benchmarking.reset_runtime
|
70
41
|
end
|
71
42
|
|
72
43
|
module ClassMethods
|
@@ -29,7 +29,7 @@ module ActsAsCached
|
|
29
29
|
end
|
30
30
|
|
31
31
|
if (item = fetch_cache(cache_id)).nil?
|
32
|
-
set_cache(cache_id, block_given? ? yield : fetch_cachable_data(cache_id), options
|
32
|
+
set_cache(cache_id, block_given? ? yield : fetch_cachable_data(cache_id), options)
|
33
33
|
else
|
34
34
|
@@nil_sentinel == item ? nil : item
|
35
35
|
end
|
@@ -40,10 +40,7 @@ module ActsAsCached
|
|
40
40
|
# get_multi on your cache store. Any misses will be fetched and saved to
|
41
41
|
# the cache, and a hash keyed by cache_id will ultimately be returned.
|
42
42
|
#
|
43
|
-
# If your cache store does not support #get_multi an exception will be raised.
|
44
43
|
def get_caches(*args)
|
45
|
-
raise NoGetMulti unless cache_store.respond_to? :get_multi
|
46
|
-
|
47
44
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
48
45
|
cache_ids = args.flatten.map(&:to_s)
|
49
46
|
keys = cache_keys(cache_ids)
|
@@ -52,7 +49,7 @@ module ActsAsCached
|
|
52
49
|
keys_map = Hash[*keys.zip(cache_ids).flatten]
|
53
50
|
|
54
51
|
# Call get_multi and figure out which keys were missed based on what was a hit
|
55
|
-
hits = ActsAsCached.config[:disabled] ? {} : (
|
52
|
+
hits = ActsAsCached.config[:disabled] ? {} : (Rails.cache.read_multi(*keys) || {})
|
56
53
|
|
57
54
|
# Misses can take the form of key => nil
|
58
55
|
hits.delete_if { |key, value| value.nil? }
|
@@ -68,7 +65,7 @@ module ActsAsCached
|
|
68
65
|
missed_records = Array(fetch_cachable_data(needed_ids))
|
69
66
|
|
70
67
|
# Cache the missed records
|
71
|
-
missed_records.each { |missed_record| missed_record.set_cache(options
|
68
|
+
missed_records.each { |missed_record| missed_record.set_cache(options) }
|
72
69
|
|
73
70
|
# Return all records as a hash indexed by object cache_id
|
74
71
|
(hits.values + missed_records).index_by(&:cache_id)
|
@@ -86,15 +83,15 @@ module ActsAsCached
|
|
86
83
|
end
|
87
84
|
end
|
88
85
|
|
89
|
-
def set_cache(cache_id, value,
|
86
|
+
def set_cache(cache_id, value, options = nil)
|
90
87
|
value.tap do |v|
|
91
88
|
v = @@nil_sentinel if v.nil?
|
92
|
-
|
89
|
+
Rails.cache.write(cache_key(cache_id), v, options)
|
93
90
|
end
|
94
91
|
end
|
95
92
|
|
96
93
|
def expire_cache(cache_id = nil)
|
97
|
-
|
94
|
+
Rails.cache.delete(cache_key(cache_id))
|
98
95
|
true
|
99
96
|
end
|
100
97
|
alias :clear_cache :expire_cache
|
@@ -152,16 +149,14 @@ module ActsAsCached
|
|
152
149
|
alias :cached :caches
|
153
150
|
|
154
151
|
def cached?(cache_id = nil)
|
155
|
-
|
152
|
+
return false if ActsAsCached.config[:skip_gets]
|
153
|
+
Rails.cache.exist?(cache_key(cache_id))
|
156
154
|
end
|
157
155
|
alias :is_cached? :cached?
|
158
156
|
|
159
157
|
def fetch_cache(cache_id)
|
160
158
|
return if ActsAsCached.config[:skip_gets]
|
161
|
-
|
162
|
-
autoload_missing_constants do
|
163
|
-
cache_store(:get, cache_key(cache_id))
|
164
|
-
end
|
159
|
+
Rails.cache.read(cache_key(cache_id))
|
165
160
|
end
|
166
161
|
|
167
162
|
def fetch_cachable_data(cache_id = nil)
|
@@ -174,7 +169,7 @@ module ActsAsCached
|
|
174
169
|
end
|
175
170
|
|
176
171
|
def cache_namespace
|
177
|
-
|
172
|
+
Rails.cache.respond_to?(:namespace) ? Rails.cache.namespace : ActsAsCached.config[:namespace]
|
178
173
|
end
|
179
174
|
|
180
175
|
# Memcache-client automatically prepends the namespace, plus a colon, onto keys, so we take that into account for the max key length.
|
@@ -196,42 +191,7 @@ module ActsAsCached
|
|
196
191
|
end
|
197
192
|
|
198
193
|
def cache_key(cache_id)
|
199
|
-
[cache_name, cache_config[:version], cache_id].compact.join('
|
200
|
-
end
|
201
|
-
|
202
|
-
def cache_store(method = nil, *args)
|
203
|
-
return cache_config[:store] unless method
|
204
|
-
|
205
|
-
load_constants = %w( get get_multi ).include? method.to_s
|
206
|
-
|
207
|
-
swallow_or_raise_cache_errors(load_constants) do
|
208
|
-
cache_config[:store].send(method, *args)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
def swallow_or_raise_cache_errors(load_constants = false, &block)
|
213
|
-
load_constants ? autoload_missing_constants(&block) : yield
|
214
|
-
rescue TypeError => error
|
215
|
-
if error.to_s.include? 'Proc'
|
216
|
-
raise MarshalError, "Most likely an association callback defined with a Proc is triggered, see http://ar.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html (Association Callbacks) for details on converting this to a method based callback"
|
217
|
-
else
|
218
|
-
raise error
|
219
|
-
end
|
220
|
-
rescue Exception => error
|
221
|
-
if ActsAsCached.config[:raise_errors]
|
222
|
-
raise error
|
223
|
-
else
|
224
|
-
Rails.logger.debug "MemCache Error: #{error.message}" rescue nil
|
225
|
-
nil
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def autoload_missing_constants
|
230
|
-
yield
|
231
|
-
rescue ArgumentError, MemCache::MemCacheError => error
|
232
|
-
lazy_load ||= Hash.new { |hash, hash_key| hash[hash_key] = true; false }
|
233
|
-
if error.to_s[/undefined class|referred/] && !lazy_load[error.to_s.split.last.sub(/::$/, '').constantize] then retry
|
234
|
-
else raise error end
|
194
|
+
[cache_name, cache_config[:version], cache_id].compact.join('/').gsub(' ', '_')[0..(max_key_length - 1)]
|
235
195
|
end
|
236
196
|
end
|
237
197
|
|
@@ -245,8 +205,8 @@ module ActsAsCached
|
|
245
205
|
self.class.get_cache(cache_id(key), options, &block)
|
246
206
|
end
|
247
207
|
|
248
|
-
def set_cache(
|
249
|
-
self.class.set_cache(cache_id, self,
|
208
|
+
def set_cache(options = nil)
|
209
|
+
self.class.set_cache(cache_id, self, options)
|
250
210
|
end
|
251
211
|
|
252
212
|
def reset_cache(key = nil)
|
@@ -262,22 +222,17 @@ module ActsAsCached
|
|
262
222
|
self.class.cached? cache_id(key)
|
263
223
|
end
|
264
224
|
|
265
|
-
def cache_key
|
266
|
-
self.class.cache_key(cache_id)
|
267
|
-
end
|
268
|
-
|
269
225
|
def cache_id(key = nil)
|
270
|
-
|
271
|
-
key.nil? ? id : "#{id}:#{key}"
|
226
|
+
key.nil? ? self.cache_key : "#{self.cache_key}/#{key}"
|
272
227
|
end
|
273
228
|
|
274
229
|
def caches(method, options = {})
|
275
|
-
key = "#{
|
230
|
+
key = "#{self.cache_key}/#{method}"
|
276
231
|
if options.keys.include?(:with)
|
277
232
|
with = options.delete(:with)
|
278
|
-
self.class.get_cache("#{key}
|
233
|
+
self.class.get_cache("#{key}/#{with}", options) { send(method, with) }
|
279
234
|
elsif withs = options.delete(:withs)
|
280
|
-
self.class.get_cache("#{key}
|
235
|
+
self.class.get_cache("#{key}/#{withs}", options) { send(method, *withs) }
|
281
236
|
else
|
282
237
|
self.class.get_cache(key, options) { send(method) }
|
283
238
|
end
|
@@ -300,8 +255,4 @@ module ActsAsCached
|
|
300
255
|
expire_cache
|
301
256
|
end
|
302
257
|
end
|
303
|
-
|
304
|
-
class MarshalError < StandardError; end
|
305
|
-
class MemCache; end
|
306
|
-
class MemCache::MemCacheError < StandardError; end
|
307
258
|
end
|
@@ -3,12 +3,14 @@ require 'rails'
|
|
3
3
|
|
4
4
|
module ActsAsCached
|
5
5
|
class Railtie < Rails::Railtie
|
6
|
-
initializer 'cache_fu
|
7
|
-
ActiveSupport.on_load
|
8
|
-
|
6
|
+
initializer 'cache_fu.extends' do
|
7
|
+
ActiveSupport.on_load :active_record do
|
8
|
+
extend ActsAsCached::Mixin
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
ActiveSupport.on_load :action_controller do
|
12
|
+
include ActsAsCached::MemcacheRuntime
|
13
|
+
end
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
data/lib/cache_fu.rb
CHANGED
@@ -1,60 +1,46 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/acts_as_cached/config'
|
2
1
|
require File.dirname(__FILE__) + '/acts_as_cached/cache_methods'
|
3
2
|
require File.dirname(__FILE__) + '/acts_as_cached/benchmarking'
|
4
3
|
require File.dirname(__FILE__) + '/acts_as_cached/disabled'
|
5
|
-
require File.dirname(__FILE__) + '/acts_as_cached/railtie' if defined?(Rails
|
4
|
+
require File.dirname(__FILE__) + '/acts_as_cached/railtie' if defined?(Rails)
|
6
5
|
|
7
6
|
module ActsAsCached
|
8
7
|
@@config = {}
|
9
8
|
mattr_reader :config
|
10
9
|
|
11
10
|
def self.config=(options)
|
12
|
-
@@config =
|
11
|
+
@@config = options
|
13
12
|
end
|
14
13
|
|
15
14
|
def self.skip_cache_gets=(boolean)
|
16
15
|
ActsAsCached.config[:skip_gets] = boolean
|
17
16
|
end
|
18
17
|
|
18
|
+
def self.valued_keys
|
19
|
+
[:version, :pages, :per_page, :finder, :cache_id, :find_by, :key_size]
|
20
|
+
end
|
21
|
+
|
19
22
|
module Mixin
|
20
23
|
def acts_as_cached(options = {})
|
21
24
|
extend ClassMethods
|
22
25
|
include InstanceMethods
|
23
26
|
|
24
|
-
extend Extensions::ClassMethods if defined? Extensions::ClassMethods
|
25
|
-
include Extensions::InstanceMethods if defined? Extensions::InstanceMethods
|
26
|
-
|
27
27
|
options.symbolize_keys!
|
28
28
|
|
29
|
-
options[:store] ||= ActsAsCached.config[:store]
|
30
|
-
options[:ttl] ||= ActsAsCached.config[:ttl]
|
31
|
-
|
32
29
|
# convert the find_by shorthand
|
33
30
|
if find_by = options.delete(:find_by)
|
34
31
|
options[:finder] = "find_by_#{find_by}".to_sym
|
35
32
|
options[:cache_id] = find_by
|
36
33
|
end
|
37
34
|
|
38
|
-
cache_config.replace options.reject { |key,| not
|
39
|
-
cache_options.replace options.reject { |key,|
|
40
|
-
|
41
|
-
Disabled.add_to self and return if ActsAsCached.config[:disabled]
|
42
|
-
Benchmarking.add_to self if ActsAsCached.config[:benchmarking]
|
35
|
+
cache_config.replace options.reject { |key,| not ActsAsCached.valued_keys.include? key }
|
36
|
+
cache_options.replace options.reject { |key,| ActsAsCached.valued_keys.include? key }
|
43
37
|
end
|
44
38
|
end
|
45
|
-
|
46
|
-
class CacheException < StandardError; end
|
47
|
-
class NoCacheStore < CacheException; end
|
48
|
-
class NoGetMulti < CacheException; end
|
49
39
|
end
|
50
40
|
|
51
41
|
Rails::Application.initializer("cache_fu") do
|
52
|
-
|
53
|
-
|
54
|
-
error = "No config file found. If you used plugin version make sure you used `script/plugin install' or `rake memcached:cache_fu_install' if gem version and have memcached.yml in your config directory."
|
55
|
-
puts error
|
56
|
-
logger.error error
|
57
|
-
exit!
|
42
|
+
if File.exists?(config_file = Rails.root.join('config', 'memcached.yml'))
|
43
|
+
ActsAsCached.config = YAML.load(ERB.new(IO.read(config_file)).result)
|
58
44
|
end
|
59
|
-
ActsAsCached.config =
|
45
|
+
ActsAsCached.config = {}
|
60
46
|
end
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache_fu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
version: 0.
|
4
|
+
prerelease: 6
|
5
|
+
version: 0.2.0.pre0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Surendra Singhi
|
@@ -47,12 +47,8 @@ extra_rdoc_files: []
|
|
47
47
|
files:
|
48
48
|
- lib/acts_as_cached/benchmarking.rb
|
49
49
|
- lib/acts_as_cached/cache_methods.rb
|
50
|
-
- lib/acts_as_cached/config.rb
|
51
|
-
- lib/acts_as_cached/disabled.rb
|
52
50
|
- lib/acts_as_cached/railtie.rb
|
53
|
-
- lib/acts_as_cached/recipes.rb
|
54
51
|
- lib/cache_fu.rb
|
55
|
-
- lib/tasks/memcached.rake
|
56
52
|
- test/benchmarking_test.rb
|
57
53
|
- test/cache_test.rb
|
58
54
|
- test/config_test.rb
|
@@ -62,9 +58,6 @@ files:
|
|
62
58
|
- test/helper.rb
|
63
59
|
- test/local_cache_test.rb
|
64
60
|
- test/sti_test.rb
|
65
|
-
- defaults/extensions.rb.default
|
66
|
-
- defaults/memcached.yml.default
|
67
|
-
- defaults/memcached_ctl.default
|
68
61
|
- LICENSE
|
69
62
|
- README
|
70
63
|
has_rdoc: true
|
@@ -85,9 +78,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
79
|
none: false
|
87
80
|
requirements:
|
88
|
-
- - "
|
81
|
+
- - ">"
|
89
82
|
- !ruby/object:Gem::Version
|
90
|
-
version:
|
83
|
+
version: 1.3.1
|
91
84
|
requirements: []
|
92
85
|
|
93
86
|
rubyforge_project:
|
@@ -1,40 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# Copy this file to vendor/plugins/acts_as_cached/extensions.rb if you
|
3
|
-
# wish to extend acts_as_cached with your own instance or class methods.
|
4
|
-
#
|
5
|
-
# You can, of course, do this directly in your cached classes,
|
6
|
-
# but keeping your custom methods here allows you to define
|
7
|
-
# methods for all cached objects DRYly.
|
8
|
-
module ActsAsCached
|
9
|
-
module Extensions
|
10
|
-
module ClassMethods
|
11
|
-
##
|
12
|
-
# All acts_as_cached classes will be extended with
|
13
|
-
# this method.
|
14
|
-
#
|
15
|
-
# >> Story.multi_get_cache(13, 353, 1231, 505)
|
16
|
-
# => [<Story:13>, <Story:353>, ...]
|
17
|
-
def multi_get_cache(*ids)
|
18
|
-
ids.flatten.map { |id| get_cache(id) }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
module InstanceMethods
|
23
|
-
##
|
24
|
-
# All instances of a acts_as_cached class will be
|
25
|
-
# extended with this method.
|
26
|
-
#
|
27
|
-
# => story = Story.get_cache(1)
|
28
|
-
# => <Story:1>
|
29
|
-
# >> story.reset_included_caches
|
30
|
-
# => true
|
31
|
-
def reset_included_caches
|
32
|
-
return false unless associations = cache_config[:include]
|
33
|
-
associations.each do |association|
|
34
|
-
Array(send(association)).each { |item| item.reset_cache }
|
35
|
-
end
|
36
|
-
true
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
defaults:
|
2
|
-
ttl: 1800
|
3
|
-
readonly: false
|
4
|
-
urlencode: false
|
5
|
-
c_threshold: 10000
|
6
|
-
compression: true
|
7
|
-
debug: false
|
8
|
-
namespace: app
|
9
|
-
sessions: false
|
10
|
-
memory: 64
|
11
|
-
servers: localhost:11211
|
12
|
-
benchmarking: true
|
13
|
-
raise_errors: true
|
14
|
-
fast_hash: false
|
15
|
-
fastest_hash: false
|
16
|
-
|
17
|
-
development:
|
18
|
-
sessions: false
|
19
|
-
fragments: false
|
20
|
-
servers: localhost:11211
|
21
|
-
|
22
|
-
# turn off caching
|
23
|
-
test:
|
24
|
-
disabled: true
|
25
|
-
|
26
|
-
production:
|
27
|
-
memory: 256
|
28
|
-
benchmarking: false
|
29
|
-
servers:
|
30
|
-
- 192.185.254.121:11211
|
31
|
-
- 192.185.254.138:11211
|
32
|
-
- 192.185.254.160:11211
|
@@ -1,81 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# By atmos@atmos.org
|
3
|
-
# this goes in your script/ directory
|
4
|
-
# it parses your memcached.yml file and hooks you up w/ some info
|
5
|
-
# it keeps you from having to mess w/ stale memcached daemons for whatever reason.
|
6
|
-
require 'yaml'
|
7
|
-
require 'timeout'
|
8
|
-
require 'erb'
|
9
|
-
|
10
|
-
class MemcachedCtl
|
11
|
-
attr_accessor :memcached, :memory, :pids, :servers, :ip_address, :ethernet_device
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
env = ENV['RAILS_ENV'] || 'development'
|
15
|
-
self.memcached = `which memcached`.chomp
|
16
|
-
self.servers = [ ]
|
17
|
-
self.pids = { }
|
18
|
-
self.ethernet_device = ENV['ETH'] || 'eth0'
|
19
|
-
self.ip_address = get_ip_address || '0.0.0.0'
|
20
|
-
self.memory = '128'
|
21
|
-
|
22
|
-
config = YAML.load(ERB.new(IO.read((File.expand_path(File.dirname(__FILE__) + "/../config/memcached.yml")))).result)
|
23
|
-
self.servers = [ config['defaults']['servers'] ].flatten rescue ['127.0.0.1:11211']
|
24
|
-
self.servers = [ config[env]['servers'] ].flatten if config[env]['servers']
|
25
|
-
self.servers.reject! { |server| host,port = server.split(/:/); self.ip_address == host }
|
26
|
-
self.memory = config[env]['memory'] unless config[env]['memory'].nil?
|
27
|
-
|
28
|
-
each_server do |host,port|
|
29
|
-
`ps auwwx | grep memcached | grep '\\-l #{ip_address} \\-p #{port}' | grep -v grep`.split(/\n/).each do |line|
|
30
|
-
self.pids[port] = line.split(/\s+/)[1]
|
31
|
-
end
|
32
|
-
self.pids[port] ||= 'Down'
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def execute(cmd)
|
37
|
-
send(cmd) rescue usage
|
38
|
-
end
|
39
|
-
|
40
|
-
def restart; stop; sleep 1; start end
|
41
|
-
|
42
|
-
def status
|
43
|
-
each_server { |host,port| puts "Port #{port} -> #{pids[port] =~ /\d+/ ? 'Up' : 'Down'}" }
|
44
|
-
end
|
45
|
-
|
46
|
-
def kill
|
47
|
-
each_server { |host,port| `kill -9 #{pids[port]} > /dev/null 2>&1` if pids[port] =~ /\d+/ }
|
48
|
-
end
|
49
|
-
|
50
|
-
def stop; kill end
|
51
|
-
|
52
|
-
def start
|
53
|
-
each_server do |host,port|
|
54
|
-
`#{memcached} -d -m #{memory} -l #{ip_address} -p #{port}`
|
55
|
-
STDERR.puts "Try memcached_ctl status" unless $? == 0
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def usage
|
60
|
-
methods = %w[start stop restart kill status]
|
61
|
-
puts "Usage: script/memcached_ctl [ " + (methods * ' | ') + " ]"
|
62
|
-
end
|
63
|
-
|
64
|
-
protected
|
65
|
-
def each_server
|
66
|
-
servers.each do |server|
|
67
|
-
host, port = server.split(/:/)
|
68
|
-
yield host, port
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def get_ip_address # this works on linux you might have to tweak this on other oses
|
73
|
-
line = `/sbin/ifconfig #{ethernet_device} | grep inet | grep -v inet6`.chomp
|
74
|
-
if line =~ /\s*inet addr:((\d+\.){3}\d+)\s+.*/
|
75
|
-
self.ip_address = $1
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
###########################################################################
|
80
|
-
|
81
|
-
MemcachedCtl.new.execute(ARGV.first)
|
@@ -1,106 +0,0 @@
|
|
1
|
-
module ActsAsCached
|
2
|
-
module Config
|
3
|
-
extend self
|
4
|
-
|
5
|
-
@@class_config = {}
|
6
|
-
mattr_reader :class_config
|
7
|
-
|
8
|
-
def valued_keys
|
9
|
-
[ :store, :version, :pages, :per_page, :ttl, :finder, :cache_id, :find_by, :key_size ]
|
10
|
-
end
|
11
|
-
|
12
|
-
def setup(options)
|
13
|
-
config = options['defaults']
|
14
|
-
|
15
|
-
case options[Rails.env]
|
16
|
-
when Hash then config.update(options[Rails.env])
|
17
|
-
when String then config[:disabled] = true
|
18
|
-
end
|
19
|
-
|
20
|
-
config.symbolize_keys!
|
21
|
-
|
22
|
-
setup_benchmarking! if config[:benchmarking] && !config[:disabled]
|
23
|
-
|
24
|
-
setup_cache_store! config
|
25
|
-
config
|
26
|
-
end
|
27
|
-
|
28
|
-
def setup_benchmarking!
|
29
|
-
ActiveSupport.on_load(:action_controller) do
|
30
|
-
include ActsAsCached::MemcacheRuntime
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def setup_cache_store!(config)
|
35
|
-
config[:store] =
|
36
|
-
if config[:store].nil?
|
37
|
-
setup_memcache config
|
38
|
-
elsif config[:store].respond_to? :constantize
|
39
|
-
config[:store].constantize.new
|
40
|
-
else
|
41
|
-
config[:store]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def setup_memcache(config)
|
46
|
-
config[:namespace] << "-#{Rails.env}"
|
47
|
-
|
48
|
-
# if someone (e.g., interlock) already set up memcached, then
|
49
|
-
# we need to stop here
|
50
|
-
return CACHE if Object.const_defined?(:CACHE)
|
51
|
-
|
52
|
-
silence_warnings do
|
53
|
-
Object.const_set :CACHE, memcache_client(config)
|
54
|
-
Object.const_set :SESSION_CACHE, memcache_client(config) if config[:session_servers]
|
55
|
-
end
|
56
|
-
|
57
|
-
CACHE.respond_to?(:servers=) ? (CACHE.servers = Array(config.delete(:servers))) : CACHE.instance_variable_set('@servers', Array(config.delete(:servers)))
|
58
|
-
CACHE.instance_variable_get('@options')[:namespace] = config[:namespace] if CACHE.instance_variable_get('@options')
|
59
|
-
|
60
|
-
SESSION_CACHE.servers = Array(config[:session_servers]) if config[:session_servers]
|
61
|
-
|
62
|
-
setup_session_store if config[:sessions]
|
63
|
-
setup_fast_hash! if config[:fast_hash]
|
64
|
-
setup_fastest_hash! if config[:fastest_hash]
|
65
|
-
|
66
|
-
CACHE
|
67
|
-
end
|
68
|
-
|
69
|
-
def memcache_client(config)
|
70
|
-
(config[:client] || "MemCache").classify.constantize.new(config)
|
71
|
-
end
|
72
|
-
|
73
|
-
def setup_session_store
|
74
|
-
return # Set up session store like normal in config/application.rb
|
75
|
-
|
76
|
-
ActionController::Base.session_store = :mem_cache_store
|
77
|
-
cache = defined?(SESSION_CACHE) ? SESSION_CACHE : CACHE
|
78
|
-
ActionController::Session::AbstractStore::DEFAULT_OPTIONS.update(
|
79
|
-
:memcache_server => cache.servers,
|
80
|
-
:readonly => cache.readonly?,
|
81
|
-
:failover => cache.failover,
|
82
|
-
:timeout => cache.timeout,
|
83
|
-
:logger => cache.logger,
|
84
|
-
:namespace => cache.namespace
|
85
|
-
)
|
86
|
-
end
|
87
|
-
|
88
|
-
# break compatiblity with non-ruby memcache clients in exchange for speedup.
|
89
|
-
# consistent across all platforms.
|
90
|
-
def setup_fast_hash!
|
91
|
-
def CACHE.hash_for(key)
|
92
|
-
(0...key.length).inject(0) do |sum, i|
|
93
|
-
sum + key[i]
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# break compatiblity with non-ruby memcache clients in exchange for speedup.
|
99
|
-
# NOT consistent across all platforms. Object#hash gives different results
|
100
|
-
# on different architectures. only use if all your apps are running the
|
101
|
-
# same arch.
|
102
|
-
def setup_fastest_hash!
|
103
|
-
def CACHE.hash_for(key) key.hash end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module ActsAsCached
|
2
|
-
module Disabled
|
3
|
-
def fetch_cache_with_disabled(*args)
|
4
|
-
nil
|
5
|
-
end
|
6
|
-
|
7
|
-
def set_cache_with_disabled(*args)
|
8
|
-
args[1]
|
9
|
-
end
|
10
|
-
|
11
|
-
def expire_cache_with_disabled(*args)
|
12
|
-
true
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.add_to(klass)
|
16
|
-
return if klass.respond_to? :fetch_cache_with_disabled
|
17
|
-
klass.extend self
|
18
|
-
|
19
|
-
class << klass
|
20
|
-
alias_method_chain :fetch_cache, :disabled
|
21
|
-
alias_method_chain :set_cache, :disabled
|
22
|
-
alias_method_chain :expire_cache, :disabled
|
23
|
-
end
|
24
|
-
|
25
|
-
class << CACHE
|
26
|
-
include FragmentCache::DisabledExtensions
|
27
|
-
end if ActsAsCached.config[:fragments] && defined?(FragmentCache::DisabledExtensions)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,8 +0,0 @@
|
|
1
|
-
Capistrano.configuration(:must_exist).load do
|
2
|
-
%w(start stop restart kill status).each do |cmd|
|
3
|
-
desc "#{cmd} your memcached servers"
|
4
|
-
task "memcached_#{cmd}".to_sym, :roles => :app do
|
5
|
-
run "RAILS_ENV=production #{ruby} #{current_path}/script/memcached_ctl #{cmd}"
|
6
|
-
end
|
7
|
-
end
|
8
|
-
end
|
data/lib/tasks/memcached.rake
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'erb'
|
3
|
-
|
4
|
-
namespace :memcached do
|
5
|
-
desc "Start memcached locally"
|
6
|
-
task :start do
|
7
|
-
ActsAsCached::Config.memcached ActsAsCached::Config.config_args
|
8
|
-
puts "memcached started"
|
9
|
-
end
|
10
|
-
|
11
|
-
desc "Restart memcached locally"
|
12
|
-
task :restart do
|
13
|
-
Rake::Task['memcached:stop'].invoke
|
14
|
-
Rake::Task['memcached:start'].invoke
|
15
|
-
end
|
16
|
-
|
17
|
-
desc "Stop memcached locally"
|
18
|
-
task :stop do
|
19
|
-
`killall memcached`
|
20
|
-
puts "memcached killed"
|
21
|
-
end
|
22
|
-
|
23
|
-
desc "Adds the cache_fu config file"
|
24
|
-
task :cache_fu_install do
|
25
|
-
defaults_dir = File.join(File.dirname(__FILE__), '../../defaults')
|
26
|
-
|
27
|
-
config_yaml = File.join('.', 'config', 'memcached.yml')
|
28
|
-
default_yaml = File.join(defaults_dir, 'memcached.yml.default')
|
29
|
-
FileUtils.cp(default_yaml, config_yaml)
|
30
|
-
|
31
|
-
memcached_ctl = File.join('.', 'script', 'memcached_ctl')
|
32
|
-
default_ctl = File.join(defaults_dir, 'memcached_ctl.default')
|
33
|
-
FileUtils.cp(default_ctl, memcached_ctl)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
module ActsAsCached
|
38
|
-
module Config
|
39
|
-
def self.config
|
40
|
-
return @config if @config
|
41
|
-
config = YAML.load(ERB.new(IO.read(Rails.root.to_s + '/config/memcached.yml')).result)
|
42
|
-
@config = config['defaults'].merge(config['development'])
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.config_args
|
46
|
-
args = {
|
47
|
-
'-p' => Array(config['servers']).first.split(':').last,
|
48
|
-
'-c' => config['c_threshold'],
|
49
|
-
'-m' => config['memory'],
|
50
|
-
'-d' => ''
|
51
|
-
}
|
52
|
-
args.to_a * ' '
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.memcached(*args)
|
56
|
-
`/usr/bin/env memcached #{args * ' '}`
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|