revo-cache_fu 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
File without changes
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2007 Chris Wanstrath
2
+
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,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
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
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,17 @@
1
+ == cache_fu
2
+
3
+ A rewrite of acts_as_cached.
4
+
5
+ == Changes from acts_as_cached 1
6
+
7
+ - You can no longer set a 'ttl' method on a class. Instead,
8
+ pass :ttl to acts_as_cached:
9
+ >> acts_as_cached :ttl => 15.minutes
10
+
11
+ - The is_cached? method is aliased as cached?
12
+
13
+ - set_cache on an instance can take a ttl
14
+ >> @story.set_cache(15.days)
15
+
16
+
17
+ Chris Wanstrath [ chris[at]ozmm[dot]org ]
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'load_multi_rails_rake_tasks'
5
+
6
+ desc "Run all the tests"
7
+ task :default => :test
8
+
9
+ test_files = FileList['test/*test.rb']
10
+
11
+ desc 'Test the cache_fu plugin.'
12
+ task :test do
13
+ test_files.each do |file|
14
+ ruby "#{file}"
15
+ end
16
+ end
17
+
18
+ desc 'Test the cache_fu plugin against Rails 1.2.5'
19
+ task :test_with_125 do
20
+ ENV['MULTIRAILS_RAILS_VERSION'] = '1.2.5'
21
+ test_files.each do |file|
22
+ ruby "#{file}"
23
+ end
24
+ end
25
+
26
+ desc "Run cache_fu tests using a memcache daemon"
27
+ task :test_with_memcache do
28
+ test_files.each do |file|
29
+ ruby "#{file} with-memcache"
30
+ end
31
+ end
32
+
33
+ desc 'Generate RDoc documentation for the cache_fu plugin.'
34
+ Rake::RDocTask.new(:rdoc) do |rdoc|
35
+ files = ['README', 'LICENSE', 'lib/**/*.rb']
36
+ rdoc.rdoc_files.add(files)
37
+ rdoc.main = "README" # page to start on
38
+ rdoc.title = "cache_fu"
39
+ rdoc.template = File.exists?(t="/Users/chris/ruby/projects/err/rock/template.rb") ? t : "/var/www/rock/template.rb"
40
+ rdoc.rdoc_dir = 'doc' # rdoc output folder
41
+ rdoc.options << '--inline-source'
42
+ end
43
+
44
+ require 'jeweler'
45
+ Jeweler::Tasks.new do |gemspec|
46
+ gemspec.name = "cache_fu"
47
+ gemspec.summary = "Summarize your gem"
48
+ gemspec.description = "Describe your gem"
49
+ gemspec.email = "chris@ozmm.org"
50
+ gemspec.homepage = "http://github.com/defunkt/cache_fu"
51
+ gemspec.description = "DESCRIPTION!"
52
+ gemspec.authors = ["Chris Wanstrath"]
53
+ end
54
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/cache_fu.gemspec ADDED
@@ -0,0 +1,77 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cache_fu}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Chris Wanstrath"]
12
+ s.date = %q{2009-08-18}
13
+ s.description = %q{DESCRIPTION!}
14
+ s.email = %q{chris@ozmm.org}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README"
18
+ ]
19
+ s.files = [
20
+ "CHANGELOG",
21
+ "LICENSE",
22
+ "README",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "cache_fu.gemspec",
26
+ "defaults/extensions.rb.default",
27
+ "defaults/memcached.yml.default",
28
+ "defaults/memcached_ctl.default",
29
+ "init.rb",
30
+ "install.rb",
31
+ "lib/acts_as_cached.rb",
32
+ "lib/acts_as_cached/benchmarking.rb",
33
+ "lib/acts_as_cached/cache_methods.rb",
34
+ "lib/acts_as_cached/config.rb",
35
+ "lib/acts_as_cached/disabled.rb",
36
+ "lib/acts_as_cached/fragment_cache.rb",
37
+ "lib/acts_as_cached/local_cache.rb",
38
+ "lib/acts_as_cached/memcached_rails.rb",
39
+ "lib/acts_as_cached/recipes.rb",
40
+ "tasks/memcached.rake",
41
+ "test/benchmarking_test.rb",
42
+ "test/cache_test.rb",
43
+ "test/config_test.rb",
44
+ "test/disabled_test.rb",
45
+ "test/extensions_test.rb",
46
+ "test/fragment_cache_test.rb",
47
+ "test/helper.rb",
48
+ "test/local_cache_test.rb",
49
+ "test/sti_test.rb"
50
+ ]
51
+ s.homepage = %q{http://github.com/defunkt/cache_fu}
52
+ s.rdoc_options = ["--charset=UTF-8"]
53
+ s.require_paths = ["lib"]
54
+ s.rubygems_version = %q{1.3.3}
55
+ s.summary = %q{Summarize your gem}
56
+ s.test_files = [
57
+ "test/sti_test.rb",
58
+ "test/benchmarking_test.rb",
59
+ "test/local_cache_test.rb",
60
+ "test/config_test.rb",
61
+ "test/extensions_test.rb",
62
+ "test/fragment_cache_test.rb",
63
+ "test/disabled_test.rb",
64
+ "test/cache_test.rb",
65
+ "test/helper.rb"
66
+ ]
67
+
68
+ if s.respond_to? :specification_version then
69
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
70
+ s.specification_version = 3
71
+
72
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
73
+ else
74
+ end
75
+ else
76
+ end
77
+ end
@@ -0,0 +1,40 @@
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
@@ -0,0 +1,34 @@
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
+ session_servers: false
11
+ fragments: false
12
+ memory: 64
13
+ servers: localhost:11211
14
+ benchmarking: true
15
+ raise_errors: true
16
+ fast_hash: false
17
+ fastest_hash: false
18
+
19
+ development:
20
+ sessions: false
21
+ fragments: false
22
+ servers: localhost:11211
23
+
24
+ # turn off caching
25
+ test:
26
+ disabled: true
27
+
28
+ production:
29
+ memory: 256
30
+ benchmarking: false
31
+ servers:
32
+ - 192.185.254.121:11211
33
+ - 192.185.254.138:11211
34
+ - 192.185.254.160:11211
@@ -0,0 +1,81 @@
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)
data/init.rb ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'memcache'
3
+ rescue LoadError
4
+ end
5
+
6
+ begin
7
+ require 'memcached'
8
+ rescue LoadError
9
+ end
10
+
11
+ begin
12
+ require 'mem_cache_with_consistent_hashing'
13
+ rescue LoadError
14
+ end
15
+
16
+ puts "=> You should be using the `memcache-client' gem. You're using RubyMemcache!" if Object.const_defined?(:RubyMemcache)
17
+
18
+ require 'acts_as_cached'
19
+
20
+ Object.send :include, ActsAsCached::Mixin
21
+
22
+ unless File.exists? config_file = File.join(RAILS_ROOT, 'config', 'memcached.yml')
23
+ error = "No config file found. Make sure you used `script/plugin install' and have memcached.yml in your config directory."
24
+ puts error
25
+ logger.error error
26
+ exit!
27
+ end
28
+
29
+ ActsAsCached.config = YAML.load(ERB.new(IO.read(config_file)).result)
30
+
31
+ begin
32
+ require 'extensions'
33
+ rescue LoadError
34
+ end
data/install.rb ADDED
@@ -0,0 +1,58 @@
1
+ ##
2
+ # Do some checks.
3
+ puts
4
+
5
+ $errors = 0
6
+
7
+ puts "** Checking for memcached in path..."
8
+ if `which memcached`.strip.empty?
9
+ $errors += 1
10
+ puts "!! Couldn't find memcached in your path. Are you sure you installed it? !!"
11
+ puts "!! Check the README for help. You can't use acts_as_cached without it. !!"
12
+ end
13
+
14
+ puts "** Checking for memcache-client gem..."
15
+ begin
16
+ require 'rubygems'
17
+ require 'memcache'
18
+ rescue LoadError
19
+ $errors += 1
20
+ puts "!! Couldn't find memcache-client gem. You can't use acts_as_cached without it. !!"
21
+ puts "!! $ sudo gem install memcache-client !!"
22
+ end
23
+
24
+ require 'fileutils'
25
+ def copy_file(in_file, out_file)
26
+ puts "** Trying to copy #{File.basename(in_file)} to #{out_file}..."
27
+ begin
28
+ if File.exists? out_file
29
+ puts "!! You already have a #{out_file}. " +
30
+ "Please check the default for new settings or format changes. !!"
31
+ puts "!! You can find the default at #{in_file}. !!"
32
+ $errors += 1
33
+ else
34
+ FileUtils.cp(in_file, out_file)
35
+ end
36
+ rescue
37
+ $errors += 1
38
+ puts "!! Error copying #{File.basename(in_file)} to #{out_file}. Please try by hand. !!"
39
+ end
40
+ end
41
+
42
+ defaults_dir = File.join(File.dirname(__FILE__), 'defaults')
43
+
44
+ config_yaml = File.join('.', 'config', 'memcached.yml')
45
+ default_yaml = File.join(defaults_dir, 'memcached.yml.default')
46
+ copy_file(default_yaml, config_yaml)
47
+
48
+ memcached_ctl = File.join('.', 'script', 'memcached_ctl')
49
+ default_ctl = File.join(defaults_dir, 'memcached_ctl.default')
50
+ copy_file(default_ctl, memcached_ctl)
51
+
52
+ puts
53
+ print $errors.zero? ? "**" : "!!"
54
+ print " acts_as_cached installed with #{$errors.zero? ? 'no' : $errors} errors."
55
+ print " Please edit the memcached.yml file to your liking."
56
+ puts $errors.zero? ? "" : " !!"
57
+ puts "** Now would be a good time to check out the README. Enjoy your day."
58
+ puts
@@ -0,0 +1,87 @@
1
+ require 'benchmark'
2
+
3
+ module ActsAsCached
4
+ module Benchmarking #:nodoc:
5
+ def self.cache_runtime
6
+ @@cache_runtime ||= 0.0
7
+ end
8
+
9
+ def self.cache_reset_runtime
10
+ @@cache_runtime = nil
11
+ end
12
+
13
+ def cache_benchmark(title, log_level = Logger::DEBUG, use_silence = true)
14
+ return yield unless logger && logger.level == log_level
15
+ result = nil
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
44
+ end
45
+
46
+ def self.add_to(klass)
47
+ return if klass.respond_to? :fetch_cache_with_benchmarking
48
+ klass.extend self
49
+
50
+ class << klass
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_DEFAULT_LOGGER end unless respond_to? :logger
56
+ end
57
+ end
58
+
59
+ def self.inject_into_logs!
60
+ if ActionController::Base.private_method_defined?(:rendering_runtime)
61
+ # Rails < 2.2
62
+ ActionController::Base.send :alias_method_chain, :rendering_runtime, :memcache
63
+ elsif ActionController::Base.private_method_defined?(:view_runtime)
64
+ # Rails >= 2.2
65
+ ActionController::Base.send :alias_method_chain, :view_runtime, :memcache
66
+ else
67
+ raise "Unknown Rails Version?!"
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ module ActionController
74
+ class Base
75
+ def rendering_runtime_with_memcache(runtime) #:nodoc:
76
+ cache_runtime = ActsAsCached::Benchmarking.cache_runtime
77
+ ActsAsCached::Benchmarking.cache_reset_runtime
78
+ rendering_runtime_without_memcache(runtime) + (cache_runtime.nonzero? ? " | Memcache: #{"%.5f" % cache_runtime}" : '')
79
+ end
80
+
81
+ def view_runtime_with_memcache #:nodoc:
82
+ cache_runtime = ActsAsCached::Benchmarking.cache_runtime
83
+ ActsAsCached::Benchmarking.cache_reset_runtime
84
+ view_runtime_without_memcache + (cache_runtime.nonzero? ? ", Memcache: #{"%.0f" % (cache_runtime * 1000)}" : '')
85
+ end
86
+ end
87
+ end