cachetastic 2.1.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/LICENSE +21 -0
  2. data/README +57 -43
  3. data/doc/classes/Cachetastic/Adapters.html +180 -0
  4. data/doc/classes/Cachetastic/Adapters/Base.html +206 -123
  5. data/doc/classes/Cachetastic/Adapters/File.html +17 -130
  6. data/doc/classes/Cachetastic/Adapters/LocalMemory.html +7 -228
  7. data/doc/classes/Cachetastic/Adapters/Memcached.html +193 -0
  8. data/doc/classes/Cachetastic/Cache.html +425 -0
  9. data/doc/classes/Cachetastic/Cacheable.html +26 -30
  10. data/doc/classes/Cachetastic/Cacheable/ClassAndInstanceMethods.html +66 -62
  11. data/doc/classes/Cachetastic/Cacheable/ClassOnlyMethods.html +30 -30
  12. data/doc/classes/Cachetastic/Logger.html +31 -33
  13. data/doc/created.rid +1 -1
  14. data/doc/files/{lib/cachetastic/adapters/html_file_rb.html → LICENSE.html} +29 -34
  15. data/doc/files/README.html +91 -57
  16. data/doc/files/lib/cachetastic/adapters/base_rb.html +1 -39
  17. data/doc/files/lib/cachetastic/adapters/file_rb.html +1 -21
  18. data/doc/files/lib/cachetastic/adapters/local_memory_rb.html +1 -9
  19. data/doc/files/lib/cachetastic/{ruby_extensions/kernel_rb.html → adapters/memcached_rb.html} +4 -4
  20. data/doc/files/lib/cachetastic/{ruby_extensions/string_rb.html → cache_rb.html} +5 -5
  21. data/doc/files/lib/cachetastic/cacheable_rb.html +1 -1
  22. data/doc/files/lib/cachetastic/{caches/base_rb.html → extensions/string_rb.html} +5 -5
  23. data/doc/files/lib/cachetastic/logger_rb.html +1 -7
  24. data/doc/files/lib/cachetastic/{adapters/store_object_rb.html → store_object_rb.html} +3 -3
  25. data/doc/files/lib/cachetastic_rb.html +4 -95
  26. data/doc/fr_class_index.html +3 -15
  27. data/doc/fr_file_index.html +5 -16
  28. data/doc/fr_method_index.html +26 -78
  29. data/lib/cachetastic.rb +16 -70
  30. data/lib/cachetastic/adapters/base.rb +178 -76
  31. data/lib/cachetastic/adapters/file.rb +63 -46
  32. data/lib/cachetastic/adapters/local_memory.rb +36 -67
  33. data/lib/cachetastic/adapters/memcached.rb +114 -0
  34. data/lib/cachetastic/cache.rb +165 -0
  35. data/lib/cachetastic/cacheable.rb +19 -15
  36. data/lib/cachetastic/extensions/string.rb +8 -0
  37. data/lib/cachetastic/logger.rb +41 -41
  38. data/lib/cachetastic/store_object.rb +22 -0
  39. metadata +43 -64
  40. data/bin/cachetastic_drb_server +0 -115
  41. data/doc/classes/ActiveRecord/Base.html +0 -194
  42. data/doc/classes/CGI/Session/CachetasticStore.html +0 -124
  43. data/doc/classes/Cachetastic/Adapters/Drb.html +0 -332
  44. data/doc/classes/Cachetastic/Adapters/FileBase.html +0 -309
  45. data/doc/classes/Cachetastic/Adapters/HtmlFile.html +0 -224
  46. data/doc/classes/Cachetastic/Adapters/Memcache.html +0 -498
  47. data/doc/classes/Cachetastic/Caches/Base.html +0 -643
  48. data/doc/classes/Cachetastic/Caches/Base/RegisteredCaches.html +0 -179
  49. data/doc/classes/Cachetastic/Caches/MackSessionCache.html +0 -119
  50. data/doc/classes/Cachetastic/Caches/PageCache.html +0 -121
  51. data/doc/classes/Cachetastic/Caches/RailsSessionCache.html +0 -154
  52. data/doc/classes/Cachetastic/Connection.html +0 -212
  53. data/doc/classes/Cachetastic/Errors/UnsupportedAdapter.html +0 -146
  54. data/doc/classes/Object.html +0 -222
  55. data/doc/classes/String.html +0 -172
  56. data/doc/files/lib/cachetastic/adapters/drb_rb.html +0 -115
  57. data/doc/files/lib/cachetastic/adapters/file_base_rb.html +0 -109
  58. data/doc/files/lib/cachetastic/adapters/memcache_rb.html +0 -127
  59. data/doc/files/lib/cachetastic/caches/mack_session_cache_rb.html +0 -107
  60. data/doc/files/lib/cachetastic/caches/page_cache_rb.html +0 -109
  61. data/doc/files/lib/cachetastic/caches/rails_session_cache_rb.html +0 -107
  62. data/doc/files/lib/cachetastic/connection_rb.html +0 -107
  63. data/doc/files/lib/cachetastic/errors/unsupported_adapter_rb.html +0 -101
  64. data/doc/files/lib/cachetastic/rails_extensions/active_record_base_rb.html +0 -101
  65. data/doc/files/lib/cachetastic/rails_extensions/cgi_session_store_rb.html +0 -109
  66. data/doc/files/lib/cachetastic/ruby_extensions/object_rb.html +0 -101
  67. data/lib/cachetastic/adapters/drb.rb +0 -51
  68. data/lib/cachetastic/adapters/file_base.rb +0 -86
  69. data/lib/cachetastic/adapters/html_file.rb +0 -68
  70. data/lib/cachetastic/adapters/memcache.rb +0 -114
  71. data/lib/cachetastic/adapters/store_object.rb +0 -28
  72. data/lib/cachetastic/caches/base.rb +0 -238
  73. data/lib/cachetastic/caches/mack_session_cache.rb +0 -3
  74. data/lib/cachetastic/caches/page_cache.rb +0 -6
  75. data/lib/cachetastic/caches/rails_session_cache.rb +0 -12
  76. data/lib/cachetastic/connection.rb +0 -24
  77. data/lib/cachetastic/errors/unsupported_adapter.rb +0 -7
  78. data/lib/cachetastic/rails_extensions/active_record_base.rb +0 -24
  79. data/lib/cachetastic/rails_extensions/cgi_session_store.rb +0 -59
  80. data/lib/cachetastic/ruby_extensions/kernel.rb +0 -25
  81. data/lib/cachetastic/ruby_extensions/object.rb +0 -22
  82. data/lib/cachetastic/ruby_extensions/string.rb +0 -15
  83. data/test/active_record_test.rb +0 -89
  84. data/test/cacheable_test.rb +0 -88
  85. data/test/cachetastic_unit_test.rb +0 -74
  86. data/test/config.rb +0 -30
  87. data/test/drb_adapter_test.rb +0 -14
  88. data/test/file_adapter_test.rb +0 -49
  89. data/test/memcache_adapter_test.rb +0 -18
  90. data/test/test_helper.rb +0 -75
@@ -1,49 +1,66 @@
1
- # This adapter uses the file system as it's backing.
2
- # The configuration for this should look something like this:
3
- # my_awesome_cache_options:
4
- # debug: false
5
- # adapter: file
6
- # marshall_method: none
7
- # default_expiry: <%= 24.hours %>
8
- # store_options:
9
- # dir: /usr/local/caches/
10
- # logging:
11
- # logger_1:
12
- # type: file
13
- # file: log/file_store_cache.log
14
- class Cachetastic::Adapters::File < Cachetastic::Adapters::FileBase
15
-
16
- def get(key)
17
- full_path = full_path_from_dir(get_key_directoy(key, false))
18
- return nil unless File.exists?(full_path)
19
- so = YAML::load(File.open(full_path).read)
20
- if so
21
- if so.invalid?
22
- self.delete(key)
1
+ module Cachetastic # :nodoc:
2
+ module Adapters
3
+ # An adapter to cache objects to the file system.
4
+ #
5
+ # This adapter supports the following configuration settings,
6
+ # in addition to the default settings:
7
+ #
8
+ # configatron.cachetastic.defaults.storage_path = ::File.join(FileUtils.pwd, 'cachetastic')
9
+ # configatron.cachetastic.defaults.marshal_method = :yaml
10
+ #
11
+ # The <tt>storage_path</tt> setting defines the path to where cached
12
+ # objects are written to on disk.
13
+ #
14
+ # See <tt>Cachetastic::Adapters::Base</tt> for a list of public API
15
+ # methods.
16
+ class File < Cachetastic::Adapters::Base
17
+
18
+ def initialize(klass) # :nodoc:
19
+ define_accessor(:storage_path)
20
+ self.storage_path = ::File.join(FileUtils.pwd, 'cachetastic')
21
+ super
22
+ self.marshal_method = :yaml if self.marshal_method == :none
23
+ @_file_paths = {}
24
+ end
25
+
26
+ def get(key) # :nodoc:
27
+ path = file_path(key)
28
+ val = nil
29
+ val = ::File.read(path) if ::File.exists?(path)
30
+ return val
31
+ end # get
32
+
33
+ def set(key, value, expiry_time = configatron.cachetastic.defaults.default_expiry) # :nodoc:
34
+ so = Cachetastic::Cache::StoreObject.new(key, value, expiry_time.from_now)
35
+ path = file_path(key)
36
+ ::File.open(path, 'w') {|f| f.write marshal(so)}
37
+ value
38
+ end # set
39
+
40
+ def delete(key) # :nodoc:
41
+ FileUtils.rm(file_path(key))
42
+ end # delete
43
+
44
+ def expire_all # :nodoc:
45
+ @_file_paths = {}
46
+ ::FileUtils.rm_rf(::File.join(self.storage_path, klass.name.underscore))
23
47
  return nil
48
+ end # expire_all
49
+
50
+ def transform_key(key) # :nodoc:
51
+ key.to_s.hexdigest
24
52
  end
25
- if so.value.is_a?(YAML::Object)
26
- require so.value.class.underscore
27
- so = YAML::load(File.open(full_path).read)
53
+
54
+ def file_path(key) # :nodoc:
55
+ path = @_file_paths[key]
56
+ if path.nil?
57
+ path = ::File.join(self.storage_path, klass.name.underscore, transform_key(key).scan(/(.{1,4})/).flatten, 'cache.data')
58
+ @_file_paths[key] = path
59
+ FileUtils.mkdir_p(::File.dirname(path))
60
+ end
61
+ return path
28
62
  end
29
- return so.value
30
- end
31
- return nil
32
- end
33
-
34
- def set(key, value, expiry = 0)
35
- so = Cachetastic::Adapters::StoreObject.new(key.to_s, value, expiry)
36
- File.open(full_path_from_key(key), "w") do |f|
37
- f.puts YAML.dump(so)
38
- end
39
- end
40
-
41
- protected
42
- def store_file_name
43
- return STORE_FILE_NAME
44
- end
45
-
46
- private
47
- STORE_FILE_NAME = "cache.yml"
48
-
49
- end
63
+
64
+ end # File
65
+ end # Adapters
66
+ end # Cachetastic
@@ -1,68 +1,37 @@
1
- # An adapter/store that keeps objects in local memory. This is great for development/testing,
2
- # but probably shouldn't be put into production.
3
- # It's also a very good example of how to write a adapter.
4
- class Cachetastic::Adapters::LocalMemory < Cachetastic::Adapters::Base
5
-
6
- attr_accessor :local_store
7
-
8
- def valid?
9
- true
10
- end
11
-
12
- def setup
13
- self.local_store = {}
14
- end
15
-
16
- def expire_all
17
- self.local_store = {}
18
- end
19
-
20
- # See Cachetastic::Adapters::Base
21
- def get(key)
22
- so = self.local_store[key.to_s]
23
- if so
24
- if so.invalid?
25
- self.delete(key)
26
- return nil
27
- end
28
- return so.value
29
- end
30
- return nil
31
- end
32
-
33
- def set(key, value, expiry = 0)
34
- self.local_store[key.to_s] = Cachetastic::Adapters::StoreObject.new(key.to_s, value, expiry)
35
- end
36
-
37
- def delete(key, delay = 0)
38
- if delay <= 0
39
- self.local_store.delete(key.to_s)
40
- else
41
- so = self.get(key)
42
- if so
43
- self.set(so.key, so.value, delay)
1
+ module Cachetastic # :nodoc:
2
+ module Adapters
3
+ # An adapter to cache objects to memory. It is important to note
4
+ # that this cache is <b>volatile</b>. If the VM it is running in
5
+ # shuts down, everything in the cache gets vaporized.
6
+ #
7
+ # See <tt>Cachetastic::Adapters::Base</tt> for a list of public API
8
+ # methods.
9
+ class LocalMemory < Cachetastic::Adapters::Base
10
+
11
+ def initialize(klass) # :nodoc:
12
+ super
13
+ @_store = {}
44
14
  end
45
- end
46
- end
47
-
48
- def stats
49
- super
50
- num_keys = self.local_store.size
51
- s = "Number of Entries: #{num_keys}\n"
52
- if num_keys > 0
53
- expiries = []
54
- keys = []
55
- self.local_store.each do |key,value|
56
- keys << key
57
- expiries << value.expires_at
58
- end
59
- expiries.sort! {|x, y| x <=> y}
60
- oldest_expiry = expiries.first
61
- newest_expiry = expiries.last
62
- s += "Oldest Entry: #{oldest_expiry}\nNewest Entry: #{newest_expiry}\nKeys: #{keys.inspect}\n"
63
- end
64
- puts s + "\n"
65
- end
66
-
67
-
68
- end
15
+
16
+ def get(key) # :nodoc:
17
+ @_store[key]
18
+ end # get
19
+
20
+ def set(key, value, expiry_time = configatron.cachetastic.defaults.default_expiry) # :nodoc:
21
+ so = Cachetastic::Cache::StoreObject.new(key, value, expiry_time.from_now)
22
+ @_store[key] = marshal(so)
23
+ value
24
+ end # set
25
+
26
+ def delete(key) # :nodoc:
27
+ @_store.delete(key)
28
+ end # delete
29
+
30
+ def expire_all # :nodoc:
31
+ @_store = {}
32
+ return nil
33
+ end # expire_all
34
+
35
+ end # LocalMemory
36
+ end # Adapters
37
+ end # Cachetastic
@@ -0,0 +1,114 @@
1
+ module Cachetastic # :nodoc:
2
+ module Adapters
3
+ # An adapter to cache objects to the file system.
4
+ #
5
+ # This adapter supports the following configuration settings,
6
+ # in addition to the default settings:
7
+ #
8
+ # configatron.cachetastic.defaults.servers = ['127.0.0.1:11211']
9
+ # configatron.cachetastic.defaults.mc_options = {:c_threshold => 10_000,
10
+ # :compression => true,
11
+ # :debug => false,
12
+ # :readonly => false,
13
+ # :urlencode => false}
14
+ # configatron.cachetastic.delete_delay = 0
15
+ #
16
+ # The <tt>servers</tt> setting defines an <tt>Array</tt> of Mecached
17
+ # servers, represented as "<host>:<port>".
18
+ #
19
+ # The <tt>mc_options</tt> setting is a <tt>Hash</tt> of settings required
20
+ # by Memcached. See the Memcached documentation for more information on
21
+ # what the settings mean.
22
+ #
23
+ # The <tt>delete_delay</tt> setting tells Memcached how long to wait
24
+ # before it deletes the object. This is not the same as <tt>expiry_time</tt>.
25
+ # It is only used when the <tt>delete</tt> method is called.
26
+ #
27
+ # See <tt>Cachetastic::Adapters::Base</tt> for a list of public API
28
+ # methods.
29
+ class Memcached < Cachetastic::Adapters::Base
30
+
31
+ def initialize(klass) # :nodoc:
32
+ define_accessor(:servers)
33
+ define_accessor(:mc_options)
34
+ define_accessor(:delete_delay)
35
+ self.delete_delay = 0
36
+ self.servers = ['127.0.0.1:11211']
37
+ self.mc_options = {:c_threshold => 10_000,
38
+ :compression => true,
39
+ :debug => false,
40
+ :readonly => false,
41
+ :urlencode => false}
42
+ super
43
+ connection
44
+ end
45
+
46
+ def get(key) # :nodoc:
47
+ connection.get(transform_key(key), false)
48
+ end # get
49
+
50
+ def set(key, value, expiry_time = configatron.cachetastic.defaults.default_expiry) # :nodoc:
51
+ connection.set(transform_key(key), marshal(value), expiry_time, false)
52
+ end # set
53
+
54
+ def delete(key) # :nodoc:
55
+ connection.delete(transform_key(key), self.delete_delay)
56
+ end # delete
57
+
58
+ def expire_all # :nodoc:
59
+ increment_version
60
+ @_mc_connection = nil
61
+ return nil
62
+ end # expire_all
63
+
64
+ def transform_key(key) # :nodoc:
65
+ key.to_s.hexdigest
66
+ end
67
+
68
+ # Return <tt>false</tt> if the connection to Memcached is
69
+ # either <tt>nil</tt> or not active.
70
+ def valid?
71
+ return false if @_mc_connection.nil?
72
+ return false unless @_mc_connection.active?
73
+ return true
74
+ end
75
+
76
+ private
77
+ def connection
78
+ unless @_mc_connection && valid? && @_ns_version == get_version
79
+ @_mc_connection = MemCache.new(self.servers, self.mc_options.merge(:namespace => namespace))
80
+ end
81
+ @_mc_connection
82
+ end
83
+
84
+ def ns_connection
85
+ unless @_ns_connection
86
+ @_ns_connection = MemCache.new(self.servers, self.mc_options.merge(:namespace => :namespace_versions))
87
+ end
88
+ @_ns_connection
89
+ end
90
+
91
+ def increment_version
92
+ name = self.klass.name
93
+ v = get_version
94
+ ns_connection.set(name, v + 1)
95
+ end
96
+
97
+ def get_version
98
+ name = self.klass.name
99
+ v = ns_connection.get(name)
100
+ if v.nil?
101
+ ns_connection.set(name, 1)
102
+ v = 1
103
+ end
104
+ v
105
+ end
106
+
107
+ def namespace
108
+ @_ns_version = get_version
109
+ "#{self.klass.name}.#{@_ns_version}"
110
+ end
111
+
112
+ end # Memcached
113
+ end # Adapters
114
+ end # Cachetastic
@@ -0,0 +1,165 @@
1
+ module Cachetastic # :nodoc:
2
+ # When creating a new 'Cache' this class should be extended.
3
+ # Once extended you'll only need to override just the methods
4
+ # that are different for your cache.
5
+ # class MyAwesomeCache < Cachetastic::Cache
6
+ # end
7
+ #
8
+ # MyAwesomeCache.set(1, "One")
9
+ # MyAwesomeCache.get(1) # => "One"
10
+ # MyAwesomeCache.update(1, "One!!")
11
+ # MyAwesomeCache.get(1) # => "One!!"
12
+ # MyAwesomeCache.delete(1)
13
+ # MyAwesomeCache.get(1) # => nil
14
+ #
15
+ # class MyAwesomeCache < Cachetastic::Cache
16
+ # class << self
17
+ # def get(key)
18
+ # super(key) do
19
+ # set(key, key * 10)
20
+ # end
21
+ # end
22
+ # end
23
+ # end
24
+ #
25
+ # MyAwesomeCache.set(1, "One")
26
+ # MyAwesomeCache.get(1) # => "One"
27
+ # MyAwesomeCache.delete(1)
28
+ # MyAwesomeCache.get(1) # => 10
29
+ class Cache
30
+
31
+ # everything is done at the class level. there won't be any 'instances of it'
32
+ # using class << self means we don't have to prefix each method with 'self.'
33
+ class << self
34
+
35
+ # Returns an object from the cache for a given key.
36
+ # If the object comes back as nil and a block is given
37
+ # that block will be run and the results of the block
38
+ # will be returned. This can be used to JIT caches, just make
39
+ # sure in the block to call the set method because the
40
+ # results of the block are not automatically cached.
41
+ def get(key, &block)
42
+ do_with_logging(:get, key) do
43
+ val = self.adapter.get(key)
44
+ handle_store_object(key, adapter.unmarshal(val), &block)
45
+ end
46
+ end # get
47
+
48
+ # Set a particular object info the cache for the given key.
49
+ #
50
+ # An optional third parameter sets the expiry time for the object in the cache.
51
+ # If no expiry_time is passed in then the default expiry_time that has been configured
52
+ # will be used.
53
+ #
54
+ # If there is an the expiry_swing setting is configured it will be +/- to the
55
+ # expiry time.
56
+ def set(key, value, expiry_time = nil)
57
+ do_with_logging(:set, key) do
58
+ self.adapter.set(key, value, calculate_expiry_time(expiry_time))
59
+ end
60
+ end # set
61
+
62
+ # Deletes an object from the cache.
63
+ def delete(key)
64
+ do_with_logging(:delete, key) do
65
+ self.adapter.delete(key)
66
+ nil
67
+ end
68
+ end # delete
69
+
70
+ # Expires all objects for this cache.
71
+ def expire_all
72
+ do_with_logging(:expire_all, nil) do
73
+ self.adapter.expire_all
74
+ nil
75
+ end
76
+ end # expire_all
77
+
78
+ # Returns the underlying Cachetastic::Adapters::Base for this cache.
79
+ def adapter
80
+ unless @_adapter && @_adapter.valid?
81
+ @_adapter = Cachetastic::Adapters.build(cache_klass)
82
+ end
83
+ @_adapter
84
+ end # adapter
85
+
86
+ # Clears the adapter so it can be redefined. This is useful if you have
87
+ # reconfigured the cache to use a different adapater, or different settings.
88
+ def clear_adapter!
89
+ @_adapter = nil
90
+ end
91
+
92
+ def cache_klass # :nodoc:
93
+ self
94
+ end
95
+
96
+ # Returns the Cachetastic::Logger for this cache.
97
+ def logger
98
+ unless @_logger
99
+ @_logger = Cachetastic::Logger.new(adapter.logger)
100
+ end
101
+ @_logger
102
+ end
103
+
104
+ private
105
+ # If the expiry time is set to 60 minutes and the expiry_swing time is set to
106
+ # 15 minutes, this method will return a number between 45 minutes and 75 minutes.
107
+ def calculate_expiry_time(expiry_time) # :doc:
108
+ expiry_time = self.adapter.default_expiry if expiry_time.nil?
109
+ exp_swing = self.adapter.expiry_swing
110
+ if exp_swing && exp_swing != 0
111
+ swing = rand(exp_swing.to_i)
112
+ case rand(2)
113
+ when 0
114
+ expiry_time = (expiry_time.to_i + swing)
115
+ when 1
116
+ expiry_time = (expiry_time.to_i - swing)
117
+ end
118
+ end
119
+ expiry_time
120
+ end
121
+
122
+ def handle_store_object(key, val, &block)
123
+ if val.is_a?(Cachetastic::Cache::StoreObject)
124
+ if val.expired?
125
+ self.delete(key)
126
+ val = nil
127
+ else
128
+ val = val.value
129
+ end
130
+ end
131
+
132
+ if val.respond_to?(:empty?)
133
+ val = nil if val.empty?
134
+ elsif val.respond_to?(:blank?)
135
+ val = nil if val.blank?
136
+ end
137
+ return val unless val.nil?
138
+
139
+ val = yield if block_given?
140
+ return val
141
+ end
142
+
143
+ def do_with_logging(action, key)
144
+ if adapter.debug?
145
+ start_time = Time.now
146
+ logger.debug(:starting, action, cache_klass.name, key)
147
+ res = yield if block_given?
148
+ end_time = Time.now
149
+ str = ''
150
+ unless res.nil?
151
+ str = "[#{res.class.name}]"
152
+ str << "\t[Size = #{res.size}]" if res.respond_to? :size
153
+ str << "\t" << res.inspect
154
+ end
155
+ logger.debug(:finished, action, cache_klass.name, key, (end_time - start_time), str)
156
+ return res
157
+ else
158
+ return yield if block_given?
159
+ end
160
+ end
161
+
162
+ end # class << self
163
+
164
+ end # Cache
165
+ end # Cachetastic