cache_fu 0.1.5 → 0.2.0.pre0
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/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
|