cachetastic 2.1.4 → 3.0.0

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.
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