Class: Card::Cache::Persistent

Inherits:
Object
  • Object
show all
Defined in:
lib/card/cache/persistent.rb

Overview

Persistent (or Hard) caches closely mirror the database and are intended to be altered only upon database alterations.

Unlike the database, the persistent cache stores records of records that have been requested but are missing or, in the case of some cards, "virtual", meaning that they follow known patterns but do not exist in the database.

Most persistent cache implementations cannot store objects with singleton classes, therefore cards generally must have set_modules re-included after retrieval from the persistent cache.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ Persistent

Returns a new instance of Persistent.

Parameters:

  • opts (Hash)

Options Hash (opts):

  • :store (Rails::Cache)
  • :class, (ruby Class)

    typically ActiveRecord descendant

  • :database (String)


35
36
37
38
39
40
# File 'lib/card/cache/persistent.rb', line 35

def initialize opts
  @store = opts[:store]
  @klass = opts[:class]
  @class_key = @klass.to_s.to_name.key
  @database = opts[:database] || self.class.database_name
end

Instance Attribute Details

#prefixObject

prefix added to cache key to create a system-wide unique key



80
81
82
# File 'lib/card/cache/persistent.rb', line 80

def prefix
  @prefix
end

Class Method Details

.database_nameObject

TODO:

find better home for this method

name of current database; used here to insure that different databases are cached separately



24
25
26
27
28
# File 'lib/card/cache/persistent.rb', line 24

def database_name
  @database_name ||= (cfg = Cardio.config) &&
                     (dbcfg = cfg.database_configuration) &&
                     dbcfg[Rails.env]["database"]
end

Instance Method Details

#annihilateObject

the nuclear option. can affect other applications sharing the same cache engine. keep in mind mutually assured destruction.



58
59
60
# File 'lib/card/cache/persistent.rb', line 58

def annihilate
  @store.clear
end

#delete(key) ⇒ Object



120
121
122
# File 'lib/card/cache/persistent.rb', line 120

def delete key
  @store.delete full_key(key)
end

#exist?(key) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/card/cache/persistent.rb', line 124

def exist? key
  @store.exist? full_key(key)
end

#fetch(key, &block) ⇒ Object



116
117
118
# File 'lib/card/cache/persistent.rb', line 116

def fetch key, &block
  @store.fetch full_key(key), &block
end

#full_key(key) ⇒ String

returns prefix/key

Parameters:

  • key (String)

Returns:

  • (String)


87
88
89
# File 'lib/card/cache/persistent.rb', line 87

def full_key key
  "#{prefix}/#{key}"
end

#new_stampObject

stamp generator



75
76
77
# File 'lib/card/cache/persistent.rb', line 75

def new_stamp
  Time.now.to_i.to_s 32
end

#read(key) ⇒ Object



91
92
93
# File 'lib/card/cache/persistent.rb', line 91

def read key
  @store.read full_key(key)
end

#renewObject

renew insures you're using the most current cache version by reaffirming the stamp and prefix



44
45
46
47
# File 'lib/card/cache/persistent.rb', line 44

def renew
  @stamp = nil
  @prefix = nil
end

#resetObject

reset effectively clears the cache by setting a new stamp



50
51
52
53
54
# File 'lib/card/cache/persistent.rb', line 50

def reset
  @stamp = new_stamp
  @prefix = nil
  Cardio.cache.write stamp_key, @stamp
end

#stampObject

the current time stamp. changing this value effectively resets the cache. Note that Cardio.cache is a simple Rails::Cache, not a Card::Cache object.



65
66
67
# File 'lib/card/cache/persistent.rb', line 65

def stamp
  @stamp ||= Cardio.cache.fetch stamp_key { new_stamp }
end

#stamp_keyObject

key for looking up the current stamp



70
71
72
# File 'lib/card/cache/persistent.rb', line 70

def stamp_key
  "#{@database}/#{@class_key}/stamp"
end

#write(key, value) ⇒ Object



112
113
114
# File 'lib/card/cache/persistent.rb', line 112

def write key, value
  @store.write full_key(key), value
end

#write_attribute(key, attribute, value) ⇒ Object

update an attribute of an object already in the cache

Parameters:

  • key (String)
  • attribute (String, Symbol)


98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/card/cache/persistent.rb', line 98

def write_attribute key, attribute, value
  if @store && (object = read key)
    object.instance_variable_set "@#{attribute}", value
    write key, object
  end
  value
rescue
  # FIXME: somehow read is finding Card objects with set_modules_loaded
  # That shouldn't be possible (#fetch is designed to prevent it), and
  # it immediately breaks write.  Best guess is that #read is somehow
  # shortcutting and returning current object.  need to research!
  Rails.logger.info "failed to write attribute: #{attribute}"
end