cachetastic 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ #require 'cachetastic'
@@ -0,0 +1,108 @@
1
+ class Cachetastic::Caches::Base
2
+
3
+ # everything is done at the class level. there won't be any 'instances of it'
4
+ # using class << self means we don't have to prefix each method with 'self.'
5
+ class << self
6
+
7
+ def get(key)
8
+ res = nil
9
+ do_with_logging(:get, key) do
10
+ res = store.get(key.to_s)
11
+ if res.nil?
12
+ res = yield if block_given?
13
+ else
14
+ res = unmarshall(res)
15
+ end
16
+ end
17
+ res
18
+ end
19
+
20
+ def set(key, value, expiry = (store.all_options["default_expiry"] || 0))
21
+ do_with_logging(:set, key) do
22
+ exp_swing = store.all_options["expiry_swing"]
23
+ if exp_swing
24
+ swing = rand(exp_swing.to_i)
25
+ case rand(2)
26
+ when 0
27
+ expiry = (expiry.to_i + swing)
28
+ when 1
29
+ expiry = (expiry.to_i - swing)
30
+ end
31
+ end
32
+ store.set(key.to_s, marshall(value), expiry.to_i)
33
+ logger.info('', '', :expiry, cache_name, key, expiry.to_i)
34
+ value
35
+ end
36
+ end
37
+
38
+ alias_method :put, :set
39
+
40
+ def delete(key, delay = 0)
41
+ do_with_logging(:delete, key) do
42
+ store.delete(key.to_s, delay)
43
+ end
44
+ end
45
+
46
+ def expire_all
47
+ store.expire_all
48
+ logger.info('', '', :expired, cache_name)
49
+ end
50
+
51
+ def cache_name
52
+ self.name.methodize
53
+ end
54
+
55
+ def store
56
+ cache_conn_instance.get(cache_name)
57
+ end
58
+
59
+ def logger
60
+ store.logger
61
+ end
62
+
63
+ private
64
+ def marshall(value)
65
+ return case store.all_options["marshall_method"]
66
+ when "yaml"
67
+ YAML.dump(value)
68
+ else
69
+ value
70
+ end
71
+ end
72
+
73
+ def unmarshall(value)
74
+ return case store.all_options["marshall_method"]
75
+ when "yaml"
76
+ YAML.load(value)
77
+ else
78
+ value
79
+ end
80
+ end
81
+
82
+ def cache_conn_instance
83
+ Cachetastic::Connection.instance
84
+ end
85
+
86
+ def do_with_logging(action, key)
87
+ start_time = Time.now
88
+ logger.info(:starting, action, cache_name, key)
89
+ res = yield if block_given?
90
+ end_time = Time.now
91
+ str = ""
92
+ unless res.nil?
93
+ str = "[#{res.class.name}]"
94
+ str << "\t[Size = #{res.size}]" if res.respond_to? :size
95
+ str << "\t" << res.inspect if store.debug?
96
+ end
97
+ logger.info(:finished, action, cache_name, key, (end_time - start_time), str)
98
+ res
99
+ end
100
+
101
+ # make sure people can't instaniate this object!
102
+ def new(*args)
103
+ raise MethodNotImplemented.new("You can not instaniate this class!")
104
+ end
105
+
106
+ end
107
+
108
+ end
@@ -0,0 +1,3 @@
1
+ class Cachetastic::Caches::PageCache < Cachetastic::Caches::Base
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class Cachetastic::Caches::RailsSessionCache < Cachetastic::Caches::Base
2
+
3
+ end
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'memcache'
3
+ require 'singleton'
4
+ require 'logger'
5
+ require 'yaml'
6
+ require 'zlib'
7
+ require 'pp'
8
+
9
+ module Cachetastic
10
+ module Caches
11
+ module ActiveRecord
12
+ end
13
+ end
14
+ module Stores
15
+ end
16
+ module Helpers
17
+ module ActiveRecord
18
+ end
19
+ end
20
+ end
21
+
22
+ require 'cachetastic_connection'
23
+ require 'cachetastic_logger'
24
+ require 'caches/cachetastic_caches_base'
25
+ require 'caches/cachetastic_caches_page_cache'
26
+ require 'caches/cachetastic_caches_rails_session_cache'
27
+ require 'stores/cachetastic_stores_base'
28
+ require 'stores/cachetastic_stores_memcache'
29
+ require 'stores/cachetastic_stores_local_memory'
30
+ require 'helpers/cachetastic_helpers_active_record'
31
+ require 'rails_extensions/cachetastic_active_record_base'
32
+ require 'rails_extensions/cgi_session_cachetastic_store'
@@ -0,0 +1,20 @@
1
+ class Cachetastic::Connection
2
+ include Singleton
3
+
4
+ attr_accessor :connections
5
+
6
+ def initialize
7
+ self.connections = {}
8
+ end
9
+
10
+ def get(name)
11
+ name = name.to_sym
12
+ conn = self.connections[name]
13
+ return conn if conn && conn.valid?
14
+ store = Cachetastic::Stores::Base.get_options(name)["store"].camelcase
15
+ conn = "Cachetastic::Stores::#{store}".constantize.new(name)
16
+ self.connections[name] = conn
17
+ return conn
18
+ end
19
+
20
+ end
@@ -0,0 +1,51 @@
1
+ class Cachetastic::Logger
2
+
3
+ attr_accessor :options
4
+ attr_accessor :cache_name
5
+
6
+ def initialize(options, cache_name)
7
+ self.options = options
8
+ # puts "self.options = #{self.options.inspect}"
9
+ self.cache_name = cache_name
10
+ self.options.each_pair do |n, opts|
11
+ # puts "opts: #{opts.inspect}"
12
+ # puts "asdfasfsadfaf opts[\"level\"] = #{opts["level"]}"
13
+ opts["level"] = (opts["level"] ||= "info").to_sym
14
+ end
15
+ end
16
+
17
+ LOG_LEVELS = [:fatal, :error, :warn, :info, :debug]
18
+
19
+ LOG_LEVELS.each do |level|
20
+ define_method(level) do |*args|
21
+ # puts "logging for: #{level}"
22
+ lm = "[CACHE] [#{level.to_s.upcase}]\t#{Time.now.strftime("%m/%d/%y %H:%m:%S")}"
23
+ exs = []
24
+ args.each do |arg|
25
+ if arg.is_a?(Exception)
26
+ exs << arg
27
+ continue
28
+ end
29
+ lm << "\t" << arg.to_s
30
+ end
31
+ exs.each do |ex|
32
+ lm << "\n#{ex.message}\n" << ex.backtrace.join("\n")
33
+ end
34
+ self.options.each_pair do |n, opts|
35
+ # puts "opts[\"level\"]: #{opts["level"]}"
36
+ # # if level == opts["level"]
37
+ # puts "LOG_LEVELS.index(opts[\"level\"]): #{LOG_LEVELS.index(opts["level"])} (#{opts["level"]})"
38
+ # puts "LOG_LEVELS.index(level): #{LOG_LEVELS.index(level)} (#{level})"
39
+ if LOG_LEVELS.index(opts["level"]) >= LOG_LEVELS.index(level)
40
+ case opts["type"]
41
+ when "file"
42
+ File.open(opts["file"], "a") {|f| f.puts(lm)}
43
+ when "console"
44
+ puts lm
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,35 @@
1
+ module Cachetastic
2
+ module Helpers
3
+ module ActiveRecord
4
+
5
+ def cache_class
6
+ n = self.class.name
7
+ n = self.name if n == "Class"
8
+ # puts "n: #{n}"
9
+ c_name = "Cachetastic::Caches::ActiveRecord::#{n}Cache"
10
+ unless Cachetastic::Caches::ActiveRecord.const_defined?("#{n}Cache")
11
+ # puts "we need to create a cache for: #{c_name}"
12
+ eval %{
13
+ class #{c_name} < Cachetastic::Caches::Base
14
+ end
15
+ }
16
+ end
17
+ c_name.constantize
18
+ end
19
+
20
+ def cache(key, expiry = 0)
21
+ cache_class.get(key) do
22
+ if block_given?
23
+ res = yield
24
+ cache_class.set(key, res, expiry)
25
+ end
26
+ end
27
+ end
28
+
29
+ def expire_all
30
+ cache_class.expire_all
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ class ActiveRecord::Base
2
+
3
+ include Cachetastic::Helpers::ActiveRecord # include helpers at instance level
4
+
5
+ class << self
6
+ include Cachetastic::Helpers::ActiveRecord # include helpers at class level
7
+
8
+ def get_from_cache(key, self_populate = false)
9
+ res = cache_class.get(key)
10
+ if res.nil? && self_populate
11
+ res = self.name.constantize.find(key)
12
+ unless res.nil?
13
+ res.cache_self
14
+ end
15
+ end
16
+ res
17
+ end
18
+
19
+ def delete_from_cache(key)
20
+ cache_class.delete(key)
21
+ end
22
+
23
+ def set_into_cache(key, value, expiry = 0)
24
+ cache_class.set(key, value, expiry)
25
+ end
26
+
27
+ end
28
+
29
+ def cache_self
30
+ cache_class.set(self.id, self) unless self.new_record?
31
+ end
32
+
33
+ def uncache_self
34
+ cache_class.delete(self.id) unless self.new_record?
35
+ end
36
+
37
+ end
@@ -0,0 +1,54 @@
1
+ require 'cgi'
2
+ require 'cgi/session'
3
+
4
+ class CGI #:nodoc:all
5
+ class Session
6
+ class CachetasticStore
7
+
8
+ def check_id(id) #:nodoc:#
9
+ /[^0-9a-zA-Z]+/ =~ id.to_s ? false : true
10
+ end
11
+
12
+ def initialize(session, options = {})
13
+ id = session.session_id
14
+ unless check_id(id)
15
+ raise ArgumentError, "session_id '%s' is invalid" % id
16
+ end
17
+
18
+ @session_key = id
19
+
20
+ @session_data = {}
21
+ end
22
+
23
+ # Restore session state from the session's memcache entry.
24
+ #
25
+ # Returns the session state as a hash.
26
+ def restore
27
+ @session_data = Cachetastic::Caches::RailsSessionCache.get(@session_key) do
28
+ {}
29
+ end
30
+ end
31
+
32
+ # Save session state to the session's memcache entry.
33
+ def update
34
+ Cachetastic::Caches::RailsSessionCache.set(@session_key, @session_data)
35
+ end
36
+
37
+ # Update and close the session's memcache entry.
38
+ def close
39
+ update
40
+ end
41
+
42
+ # Delete the session's memcache entry.
43
+ def delete
44
+ Cachetastic::Caches::RailsSessionCache.delete(@session_key)
45
+ @session_data = {}
46
+ end
47
+
48
+ def data
49
+ @session_data
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,70 @@
1
+ class Cachetastic::Stores::Base
2
+
3
+ attr_reader :all_options
4
+ attr_reader :store_options
5
+ attr_reader :servers
6
+ attr_reader :name
7
+ attr_reader :logging
8
+ attr_reader :logger
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ configure
13
+ setup
14
+ if self.debug?
15
+ self.logger.debug(self.name, :self, self.inspect)
16
+ self.logger.debug(self.name, :options, self.all_options.inspect)
17
+ end
18
+ end
19
+
20
+ def valid?
21
+ false
22
+ end
23
+
24
+ [:setup, :set, :get, :delete, :expire_all].each do |meth|
25
+ define_method(meth) do |*args|
26
+ raise MethodNotImplemented.new(meth)
27
+ end
28
+ end
29
+
30
+ def debug?
31
+ ivar_cache(:debug) do
32
+ (self.all_options["debug"] == true || false)
33
+ end
34
+ end
35
+
36
+ def configure
37
+ @all_options = Cachetastic::Stores::Base.get_options(self.name)
38
+ @store_options = (self.all_options["store_options"] || {})
39
+ @servers = self.all_options["servers"]
40
+ @logging = (self.all_options["logging"] || {})
41
+ @logger = Cachetastic::Logger.new(self.logging, self.name)
42
+ end
43
+
44
+ # def log(mess, ex = nil)
45
+ # self.logging.each_pair do |n, opts|
46
+ #
47
+ # lm = "[CACHE]\t#{Time.now}:\t#{mess}"
48
+ # lm << "\n#{ex.message}\n" << ex.backtrace.join("\n") if ex
49
+ #
50
+ # case opts["type"]
51
+ # when "file"
52
+ # File.open(opts["file"], "a") {|f| f.puts(lm)}
53
+ # when "console"
54
+ # puts lm
55
+ # end
56
+ # end
57
+ # end
58
+
59
+
60
+
61
+ class << self
62
+ def get_options(name)
63
+ options = app_config.cachetastic_default_options
64
+ options.merge!(app_config.send(name.methodize + "_options") || {})
65
+ options = {"store" => "local_memory"}.merge(options)
66
+ options
67
+ end
68
+ end
69
+
70
+ end
@@ -0,0 +1,71 @@
1
+ class Cachetastic::Stores::LocalMemory < Cachetastic::Stores::Base
2
+
3
+ attr_accessor :local_store
4
+
5
+ def valid?
6
+ true
7
+ end
8
+
9
+ def setup
10
+ self.local_store = {}
11
+ end
12
+
13
+ def expire_all
14
+ self.local_store = {}
15
+ end
16
+
17
+ def get(key)
18
+ so = self.local_store[key.to_s]
19
+ if so
20
+ if Time.now >= so.expires_at
21
+ self.delete(key)
22
+ return nil
23
+ end
24
+ return so.value
25
+ end
26
+ return nil
27
+ end
28
+
29
+ def set(key, value, expiry = 0)
30
+ self.local_store[key.to_s] = StoreObject.new(key.to_s, value, expiry)
31
+ end
32
+
33
+ def delete(key, delay = 0)
34
+ if delay <= 0
35
+ self.local_store.delete(key.to_s)
36
+ else
37
+ so = self.get(key)
38
+ if so
39
+ self.set(so.key, so.value, delay)
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+ class StoreObject
46
+ attr_accessor :key
47
+ attr_accessor :value
48
+ attr_accessor :expires_at
49
+
50
+ def initialize(key, value, expiry)
51
+ # puts "expiry: #{expiry}"
52
+ self.key = key
53
+ self.value = value
54
+ begin
55
+ self.expires_at = (Time.now + (expiry == 0 ? (31536000) : expiry)) # 31536000 = one year
56
+ rescue RangeError => e
57
+ self.expires_at = Time.at(expiry)
58
+ end
59
+ # puts "now: #{Time.now}"
60
+ # puts "expiry: #{expiry}"
61
+ # puts "expires_at: #{self.expires_at}"
62
+ end
63
+
64
+ def size
65
+ return self.value.size if self.value.respond_to?(:size)
66
+ -1
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,67 @@
1
+ class Cachetastic::Stores::Memcache < Cachetastic::Stores::Base
2
+
3
+ def setup
4
+ self.conn = MemCache.new(self.servers, self.store_options.merge({:namespace => self.namespace}))
5
+ self.version = self.get_version(self.name)
6
+ end
7
+
8
+ def set(key, value, expiry = 0)
9
+ self.conn.set(key, value, expiry)
10
+ end
11
+
12
+ def delete(key, delay = 0)
13
+ self.conn.delete(key, delay)
14
+ end
15
+
16
+ def get(key)
17
+ self.conn.get(key)
18
+ end
19
+
20
+ def expire_all
21
+ self.increment_version(self.name)
22
+ end
23
+
24
+ def inspect
25
+ self.conn.inspect + " <version: #{self.version}> #{self.conn.stats.inspect}"
26
+ end
27
+
28
+ def namespace
29
+ v = self.get_version(self.name)
30
+ return "#{name}.#{v}"
31
+ end
32
+
33
+ def valid?
34
+ begin
35
+ return (self.active? && self.version == self.get_version(self.name))
36
+ rescue Exception => e
37
+ return false
38
+ end
39
+ end
40
+
41
+ protected
42
+ attr_accessor :conn
43
+ attr_accessor :version
44
+
45
+ def ns_versions
46
+ ivar_cache do
47
+ ns_conn = MemCache.new(self.servers, self.store_options.merge({:namespace => :namespace_versions}))
48
+ end
49
+ end
50
+
51
+ def increment_version(name)
52
+ name = name.to_s
53
+ v = get_version(name)
54
+ self.ns_versions.set(name, v + 1)
55
+ end
56
+
57
+ def get_version(name)
58
+ name = name.to_s
59
+ v = self.ns_versions.get(name)
60
+ if v.nil?
61
+ self.ns_versions.set(name, 1)
62
+ v = 1
63
+ end
64
+ v
65
+ end
66
+
67
+ end
@@ -0,0 +1,5 @@
1
+ --- !ruby/object:RubyForgeConfig
2
+ gem_name: cachetastic
3
+ package: cachetastic
4
+ project: magrathea
5
+ version: 1.0.5
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: cachetastic
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.5
7
+ date: 2007-12-28 00:00:00 -05:00
8
+ summary: cachetastic
9
+ require_paths:
10
+ - lib
11
+ - lib
12
+ email:
13
+ homepage:
14
+ rubyforge_project: magrathea
15
+ description: "cachetastic was developed by: markbates"
16
+ autorequire:
17
+ - cachetastic
18
+ default_executable:
19
+ bindir: bin
20
+ has_rdoc: false
21
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
22
+ requirements:
23
+ - - ">"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.0.0
26
+ version:
27
+ platform: ruby
28
+ signing_key:
29
+ cert_chain:
30
+ post_install_message:
31
+ authors:
32
+ - markbates
33
+ files:
34
+ - init.rb
35
+ - lib/caches/cachetastic_caches_base.rb
36
+ - lib/caches/cachetastic_caches_page_cache.rb
37
+ - lib/caches/cachetastic_caches_rails_session_cache.rb
38
+ - lib/cachetastic.rb
39
+ - lib/cachetastic_connection.rb
40
+ - lib/cachetastic_logger.rb
41
+ - lib/helpers/cachetastic_helpers_active_record.rb
42
+ - lib/rails_extensions/cachetastic_active_record_base.rb
43
+ - lib/rails_extensions/cgi_session_cachetastic_store.rb
44
+ - lib/stores/cachetastic_stores_base.rb
45
+ - lib/stores/cachetastic_stores_local_memory.rb
46
+ - lib/stores/cachetastic_stores_memcache.rb
47
+ - lib/tasks/rubyforge_config.yml
48
+ test_files: []
49
+
50
+ rdoc_options: []
51
+
52
+ extra_rdoc_files: []
53
+
54
+ executables: []
55
+
56
+ extensions: []
57
+
58
+ requirements: []
59
+
60
+ dependencies: []
61
+