cachetastic 1.0.5

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/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
+