mack-caching 0.8.1 → 0.8.2

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