mack-caching 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. data/lib/gems/cachetastic-2.0.0/bin/cachetastic_drb_server +115 -0
  2. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/adapters/base.rb +78 -0
  3. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/adapters/drb.rb +51 -0
  4. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/adapters/file.rb +49 -0
  5. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/adapters/file_base.rb +86 -0
  6. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/adapters/html_file.rb +68 -0
  7. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/adapters/local_memory.rb +68 -0
  8. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/adapters/memcache.rb +114 -0
  9. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/adapters/store_object.rb +28 -0
  10. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/cacheable.rb +196 -0
  11. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/caches/base.rb +238 -0
  12. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/caches/mack_session_cache.rb +3 -0
  13. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/caches/page_cache.rb +6 -0
  14. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/caches/rails_session_cache.rb +12 -0
  15. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/connection.rb +24 -0
  16. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/errors/unsupported_adapter.rb +7 -0
  17. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/logger.rb +49 -0
  18. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/rails_extensions/active_record_base.rb +24 -0
  19. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/rails_extensions/cgi_session_store.rb +59 -0
  20. data/lib/gems/cachetastic-2.0.0/lib/cachetastic/ruby_extensions/object.rb +8 -0
  21. data/lib/gems/cachetastic-2.0.0/lib/cachetastic.rb +70 -0
  22. data/lib/gems/memcache-client-1.5.0/lib/memcache.rb +805 -0
  23. data/lib/gems/memcache-client-1.5.0/lib/memcache_util.rb +90 -0
  24. data/lib/gems.rb +13 -0
  25. data/lib/mack-caching.rb +2 -1
  26. data/lib/mack-caching_tasks.rb +2 -0
  27. metadata +51 -16
@@ -0,0 +1,115 @@
1
+ #!/usr/local/bin/ruby
2
+ require 'thread'
3
+ require 'drb'
4
+ require 'singleton'
5
+ require 'optparse'
6
+ require 'optparse/time'
7
+ require 'ostruct'
8
+
9
+ # require the necessary gems:
10
+ require 'rubygems'
11
+ gem 'mack-facets'
12
+ require 'mack-facets'
13
+ gem 'configatron'
14
+ require 'configatron'
15
+ gem 'cachetastic'
16
+ require 'cachetastic'
17
+
18
+ $SAFE = 1
19
+
20
+ SERVER_OPTIONS = OpenStruct.new
21
+ SERVER_OPTIONS.host = "127.0.0.1"
22
+ SERVER_OPTIONS.port = "61676"
23
+ SERVER_OPTIONS.config_file = nil
24
+ SERVER_OPTIONS.verbose = false
25
+ SERVER_OPTIONS.really_verbose = false
26
+
27
+ opts = OptionParser.new do |opts|
28
+
29
+ opts.on("-h [HOST]") do |v|
30
+ SERVER_OPTIONS.host = v
31
+ end
32
+
33
+ opts.on("-p [PORT]", Integer) do |v|
34
+ SERVER_OPTIONS.port = v
35
+ end
36
+
37
+ opts.on("-c [CONFIG_FILE]") do |v|
38
+ SERVER_OPTIONS.config_file = v
39
+ end
40
+
41
+ opts.on("-v") do |v|
42
+ SERVER_OPTIONS.verbose = true
43
+ end
44
+
45
+ opts.on("-rv") do |v|
46
+ SERVER_OPTIONS.verbose = true
47
+ SERVER_OPTIONS.really_verbose = true
48
+ end
49
+
50
+ end
51
+
52
+ opts.parse!(ARGV)
53
+
54
+ if SERVER_OPTIONS.config_file
55
+ configatron.configure_from_yaml(SERVER_OPTIONS.config_file)
56
+ end
57
+
58
+ module Cachetastic
59
+ module Drb
60
+ class Server
61
+ include Singleton
62
+
63
+ def initialize
64
+ DRb.start_service("druby://#{SERVER_OPTIONS.host}:#{SERVER_OPTIONS.port}", self)
65
+ puts "Cachetastic::Drb::Server listening for connection..."
66
+ DRb.thread.join
67
+ end # initialize
68
+
69
+ def get(ns, key)
70
+ puts "get: #{ns}.#{key}" if SERVER_OPTIONS.verbose
71
+ puts cache_for_namespace(ns).inspect if SERVER_OPTIONS.really_verbose
72
+ value = cache_for_namespace(ns).get(key)
73
+ puts "\tvalue.class: #{value.class}" if SERVER_OPTIONS.verbose
74
+ value
75
+ end
76
+
77
+ def set(ns, key, value, expiry = 0)
78
+ puts "set: #{ns}.#{key}: #{value}" if SERVER_OPTIONS.verbose
79
+ cache_for_namespace(ns).set(key, value)
80
+ puts cache_for_namespace(ns).inspect if SERVER_OPTIONS.really_verbose
81
+ value
82
+ end
83
+
84
+ def delete(ns, key, delay = 0)
85
+ puts "delete: #{ns}.#{key}" if SERVER_OPTIONS.verbose
86
+ cache_for_namespace(ns).delete(key, delay = 0)
87
+ puts cache_for_namespace(ns).inspect if SERVER_OPTIONS.really_verbose
88
+ end
89
+
90
+ def expire_all(ns)
91
+ puts "expire_all: #{ns}" if SERVER_OPTIONS.verbose
92
+ instance_variable_set("@store_for_#{ns}", Cachetastic::Adapters::LocalMemory.new("store_for_#{ns}"))
93
+ end
94
+
95
+ def ping
96
+ true
97
+ end
98
+
99
+ private
100
+ def cache_for_namespace(ns)
101
+ # puts "@store_for_#{ns}"
102
+ c = instance_variable_get("@store_for_#{ns}")
103
+ if c.nil?
104
+ instance_variable_set("@store_for_#{ns}", Cachetastic::Adapters::LocalMemory.new("store_for_#{ns}"))
105
+ c = instance_variable_get("@store_for_#{ns}")
106
+ end
107
+ c
108
+ end
109
+
110
+ end # Server
111
+ end # Drb
112
+ end # Cachetastic
113
+
114
+ # let's start `er up!
115
+ Cachetastic::Drb::Server.instance
@@ -0,0 +1,78 @@
1
+ # This class is the interface used to develop adapters for stores.
2
+ # Stores are where the data is actually held. These could be local memory,
3
+ # memcached, a database, the file system, etc...
4
+ # If you implement this API, then you should be able to plug in different
5
+ # stores for your caches without having to change any of your code.
6
+ #
7
+ # === Methods that need to be implemented:
8
+ # * setup - used to setup the implementation of the adapter.
9
+ # * set(key, object, expiry) - sets an object into the store using the given key and the expiry time.
10
+ # * get(key) - returns an object from the store for a given key.
11
+ # * delete(key, delay) - deletes an object from the store for a given key. If the store supports it, a delay can be used.
12
+ # * expire_all - expires all objects in the store for a given cache.
13
+ # * stats - returns statistics for the store.
14
+ # * valid? - used to test whether or not the store is still valid. If this returns false a new instance of the adapter is created by Cachetastic::Connection
15
+ class Cachetastic::Adapters::Base
16
+
17
+ # attr_reader :all_options
18
+ # attr_reader :store_options
19
+ # attr_reader :servers
20
+ attr_reader :name
21
+ # attr_reader :logging
22
+ attr_reader :logger
23
+
24
+ def initialize(name)
25
+ @name = name
26
+ @logger = Cachetastic::Logger.new(configuration.retrieve(:logger, ::Logger.new(STDOUT)))
27
+ setup
28
+ if self.debug?
29
+ self.logger.debug(self.name, :self, self.inspect)
30
+ end
31
+ end
32
+
33
+ needs_method :setup
34
+ needs_method :set
35
+ needs_method :get
36
+ needs_method :delete
37
+ needs_method :expire_all
38
+ needs_method :stats
39
+ needs_method :valid?
40
+
41
+ # Returns true/or falsed based on whether or not the debug setting is set to true in the
42
+ # configuration file. If the config setting is set, then false is returned.
43
+ def debug?
44
+ ivar_cache(:debug) do
45
+ configuration.retrieve(:debug, false)
46
+ end
47
+ end
48
+
49
+ def stats
50
+ cache_name = self.name.to_s.camelize
51
+ adapter_type = self.class.to_s.gsub('Cachetastic::Adapters::', '')
52
+ s = "Cache: #{cache_name}\nStore Type: #{adapter_type}\n"
53
+ if self.servers
54
+ servers = self.servers.join(',')
55
+ s += "Servers: #{servers}"
56
+ end
57
+ puts s
58
+ end
59
+
60
+ def configuration
61
+ Cachetastic::Adapters::Base.configuration(self.name)
62
+ end
63
+
64
+ class << self
65
+ # Returns either the options
66
+ # Options need to be specified in configatrion as the methodized name of the cache with
67
+ # _options attached at the end.
68
+ # Examples:
69
+ # Cachetastic::Caches::PageCache # => cachetastic_caches_page_cache_options
70
+ # MyAwesomeCache # => my_awesome_cache_options
71
+ def configuration(name)
72
+ name = "#{name}_options"
73
+ conf = configatron.retrieve(name, configatron.cachetastic_default_options)
74
+ conf
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,51 @@
1
+ # This adapter uses Cachetastic::Drb::Server as it's backing.
2
+ # The configuration for this should look something like this:
3
+ # my_awesome_cache_options:
4
+ # debug: false
5
+ # adapter: drb
6
+ # store_options:
7
+ # host: druby://127.0.0.1:61676
8
+ class Cachetastic::Adapters::Drb < Cachetastic::Adapters::Base
9
+
10
+ attr_accessor :drb_store
11
+
12
+ def valid?
13
+ begin
14
+ return self.drb_store.ping
15
+ rescue Exception => e
16
+ return false
17
+ end
18
+ end
19
+
20
+ def setup
21
+ # self.all_options["marshall_method"] = "ruby"
22
+ self.drb_store = DRbObject.new_with_uri(configuration.servers)
23
+ end
24
+
25
+ def expire_all
26
+ self.drb_store.expire_all(self.name)
27
+ end
28
+
29
+ # See Cachetastic::Adapters::Base
30
+ def get(key)
31
+ Cachetastic::Caches::Base.unmarshall(self.drb_store.get(self.name, key))
32
+ end
33
+
34
+ def set(key, value, expiry = 0)
35
+ self.drb_store.set(self.name, key, Cachetastic::Caches::Base.marshall(value), expiry)
36
+ end
37
+
38
+ def delete(key, delay = 0)
39
+ self.drb_store.delete(self.name, key)
40
+ end
41
+
42
+ def stats
43
+ super
44
+ begin
45
+ self.drb_store.stats if self.drb_store.respond_to? 'stats'
46
+ rescue Exception => e
47
+ puts "Calling stats on the DRb store raised this exception: #{e.message}"
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,49 @@
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)
23
+ return nil
24
+ end
25
+ if so.value.is_a?(YAML::Object)
26
+ require so.value.class.underscore
27
+ so = YAML::load(File.open(full_path).read)
28
+ 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
@@ -0,0 +1,86 @@
1
+ require 'digest/md5'
2
+ require 'base64'
3
+ class Cachetastic::Adapters::FileBase < Cachetastic::Adapters::Base
4
+
5
+ attr_reader :directory
6
+ attr_reader :hashed_keys
7
+
8
+ def setup
9
+ @directory = File.join(self.configuration.store_options.dir, self.name.to_s)
10
+ FileUtils.mkdir_p(self.directory, :verbose => self.debug?)
11
+ @hashed_keys = {}
12
+ end
13
+
14
+ def valid?
15
+ File.exists?(self.directory)
16
+ end
17
+
18
+ def stats
19
+ super
20
+ num_files = num_directories = file_size = 0
21
+ everything = Dir.glob("#{self.directory}/**/*")
22
+ everything.reject{|x| x =~ /^\./}.each do |entry|
23
+ if ::File.directory?(entry)
24
+ num_directories += 1
25
+ else
26
+ file_size += ::File.size(entry)
27
+ num_files += 1
28
+ end
29
+ end
30
+ puts "Number of Files: #{num_files}\nNumber of Directories: #{num_directories}\nTotal Size on Disk: #{file_size/1024.to_f} KB\n\n"
31
+ end
32
+
33
+ def delete(key, delay = 0)
34
+ if delay <= 0
35
+ FileUtils.rm_rf(get_key_directoy(key), :verbose => self.debug?)
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
+ def expire_all
45
+ FileUtils.rm_rf(self.directory, :verbose => self.debug?)
46
+ setup
47
+ end
48
+
49
+ protected
50
+ def store_file_name
51
+ return "cachetastic.data"
52
+ end
53
+
54
+ private
55
+ def directory_from_key(key)
56
+ hkey = Base64.encode64(Digest::MD5.digest(key))
57
+ hkey.gsub!("==\n", "")
58
+ i = 0
59
+ path = ""
60
+ until i >= hkey.length do
61
+ path = File.join(path, hkey[i..i+2])
62
+ i += 3
63
+ end
64
+ path
65
+ end
66
+
67
+ def full_path_from_key(key)
68
+ full_path_from_dir(get_key_directoy(key))
69
+ end
70
+
71
+ def full_path_from_dir(dir)
72
+ File.join(dir, store_file_name)
73
+ end
74
+
75
+ def get_key_directoy(key, mkdir = true)
76
+ hkey = self.hashed_keys[key.to_sym]
77
+ if hkey.nil?
78
+ path = File.join(self.directory, directory_from_key(key))
79
+ self.hashed_keys[key.to_sym] = path
80
+ hkey = path
81
+ end
82
+ FileUtils.mkdir_p(hkey, :verbose => self.debug?) if mkdir
83
+ hkey
84
+ end
85
+
86
+ end
@@ -0,0 +1,68 @@
1
+ # This adapter uses the file system as it's backing.
2
+ # Caches are stored in files called index.html.
3
+ # At the beginning of the html the following html comments are pre-pended:
4
+ # <!-- cachetastic: expires_at: Fri Feb 01 20:51:45 -0500 2008 -->
5
+ # <!-- cachetastic: key: /channels/1-arts-humanities -->
6
+ # Obviously the expires_at date will be the ACTUAL expire date,
7
+ # same goes for the key.
8
+ # The configuration for this should look something like this:
9
+ # my_awesome_cache_options:
10
+ # debug: false
11
+ # adapter: html_file
12
+ # marshall_method: none
13
+ # default_expiry: <%= 24.hours %>
14
+ # store_options:
15
+ # dir: /usr/local/caches/
16
+ # logging:
17
+ # logger_1:
18
+ # type: file
19
+ # file: log/file_store_cache.log
20
+ require 'time'
21
+ class Cachetastic::Adapters::HtmlFile < Cachetastic::Adapters::FileBase
22
+
23
+ def get(key)
24
+ full_path = full_path_from_dir(get_key_directoy(key, false))
25
+ return nil unless File.exists?(full_path)
26
+ so = html_to_store_object(File.open(full_path).read)
27
+ if so
28
+ if so.invalid?
29
+ self.delete(key)
30
+ return nil
31
+ end
32
+ return so.value
33
+ end
34
+ return nil
35
+ end
36
+
37
+ def set(key, value, expiry = 0)
38
+ so = Cachetastic::Adapters::StoreObject.new(key.to_s, value, expiry)
39
+ File.open(full_path_from_key(key), "w") do |f|
40
+ f.puts store_object_to_html(so)
41
+ end
42
+ end
43
+
44
+ protected
45
+ def store_file_name
46
+ return STORE_FILE_NAME
47
+ end
48
+
49
+ private
50
+ def html_to_store_object(html)
51
+ key = html.match(/<!-- cachetastic: key: (.*) -->/).captures.first
52
+ expires_at = html.match(/<!-- cachetastic: expires_at: (.*) -->/).captures.first
53
+ html.gsub!(/<!-- cachetastic: key: .* -->/, '')
54
+ html.gsub!(/<!-- cachetastic: expires_at: .* -->/, '')
55
+ so = Cachetastic::Adapters::StoreObject.new(key, html, 0)
56
+ so.expires_at = Time.parse(expires_at)
57
+ so
58
+ end
59
+
60
+ def store_object_to_html(so)
61
+ x = so.value
62
+ x << "\n<!-- cachetastic: expires_at: #{so.expires_at} -->"
63
+ x << "\n<!-- cachetastic: key: #{so.key} -->"
64
+ end
65
+
66
+ STORE_FILE_NAME = "index.html"
67
+
68
+ end
@@ -0,0 +1,68 @@
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)
44
+ 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
@@ -0,0 +1,114 @@
1
+ # This adapter uses Memcache as it's backing.
2
+ # The configuration for this should look something like this:
3
+ # my_awesome_cache_options:
4
+ # debug: false
5
+ # adapter: memcache
6
+ # marshall_method: none
7
+ # default_expiry: <%= 24.hours %>
8
+ # store_options:
9
+ # c_threshold: 10_000
10
+ # compression: true
11
+ # debug: false
12
+ # readonly: false
13
+ # urlencode: false
14
+ # logging:
15
+ # logger_1:
16
+ # type: file
17
+ # file: log/memcached.log
18
+ # servers:
19
+ # - 127.0.0.1:11211
20
+ class Cachetastic::Adapters::Memcache < Cachetastic::Adapters::Base
21
+
22
+ def setup
23
+ self.conn = MemCache.new(configuration.servers, configuration.store_options.to_hash.merge({:namespace => self.namespace}))
24
+ self.version = self.get_version(self.name)
25
+ end
26
+
27
+ def set(key, value, expiry = 0, raw = false)
28
+ self.conn.set(key, value, expiry, raw)
29
+ end
30
+
31
+ def delete(key, delay = 0)
32
+ self.conn.delete(key, delay)
33
+ end
34
+
35
+ def get(key, raw = false)
36
+ self.conn.get(key, raw)
37
+ end
38
+
39
+ def expire_all
40
+ self.increment_version(self.name)
41
+ end
42
+
43
+ def inspect
44
+ self.conn.inspect + " <version: #{self.version}> #{self.conn.stats.inspect}"
45
+ end
46
+
47
+ def valid?
48
+ begin
49
+ return (self.conn.active? && self.version == self.get_version(self.name))
50
+ rescue Exception => e
51
+ puts e.message
52
+ puts e.backtrace.join("\n")
53
+ return false
54
+ end
55
+ end
56
+
57
+ def stats
58
+ super
59
+ begin
60
+ puts "Memcache stats for all caches:"
61
+ memc = self.conn
62
+ puts Kernel.pp_to_s(memc.stats)
63
+ paths = `sh -c 'echo $PATH'`
64
+ paths = paths.split(':')
65
+ memcached_tool_found = false
66
+ paths.each do |path|
67
+ cmd_path = File.expand_path(File.join(path,'memcached_tool'))
68
+ if File.exists?(cmd_path)
69
+ memcached_tool_found = true
70
+ break
71
+ end
72
+ end
73
+ if memcached_tool_found
74
+ configuration.memcache_servers.each do |server|
75
+ puts `memcached_tool #{server}`
76
+ end
77
+ end
78
+ rescue
79
+ end
80
+ puts ""
81
+ end
82
+
83
+ protected
84
+ attr_accessor :conn
85
+ attr_accessor :version
86
+
87
+ def namespace
88
+ v = self.get_version(self.name)
89
+ return "#{name}.#{v}"
90
+ end
91
+
92
+ def ns_versions
93
+ ivar_cache do
94
+ ns_conn = MemCache.new(configuration.servers, configuration.store_options.to_hash.merge({:namespace => :namespace_versions}))
95
+ end
96
+ end
97
+
98
+ def increment_version(name)
99
+ name = name.to_s
100
+ v = get_version(name)
101
+ self.ns_versions.set(name, v + 1)
102
+ end
103
+
104
+ def get_version(name)
105
+ name = name.to_s
106
+ v = self.ns_versions.get(name)
107
+ if v.nil?
108
+ self.ns_versions.set(name, 1)
109
+ v = 1
110
+ end
111
+ v
112
+ end
113
+
114
+ end
@@ -0,0 +1,28 @@
1
+ class Cachetastic::Adapters::StoreObject #:nodoc:#
2
+ attr_accessor :key
3
+ attr_accessor :value
4
+ attr_accessor :expires_at
5
+
6
+ def initialize(key, value, expiry)
7
+ self.key = key
8
+ self.value = value
9
+ begin
10
+ self.expires_at = (Time.now + (expiry == 0 ? (31536000) : expiry)) # 31536000 = one year
11
+ rescue RangeError => e
12
+ self.expires_at = Time.at(expiry)
13
+ end
14
+ # puts "now: #{Time.now}"
15
+ # puts "expiry: #{expiry}"
16
+ # puts "expires_at: #{self.expires_at}"
17
+ end
18
+
19
+ def size
20
+ return self.value.size if self.value.respond_to?(:size)
21
+ -1
22
+ end
23
+
24
+ def invalid?
25
+ Time.now >= self.expires_at
26
+ end
27
+
28
+ end