Class: SQLite3::Cache
- Inherits:
-
Object
- Object
- SQLite3::Cache
- Defined in:
- lib/sqlite3_cache.rb
Instance Method Summary collapse
-
#[](key) ⇒ Object
retrieves a value from the cache.
-
#[]=(key, value) ⇒ Object
sets a value in the cache.
-
#delete!(key) ⇒ Object
deletes a key from the cache.
-
#each_pair(&block) ⇒ Object
iterate over each key and value in the namespace.
-
#exist?(key) ⇒ Boolean
checks to see if we have a given key…
-
#expiration=(expiration) ⇒ Object
The value that was passed in.
-
#initialize(options) ⇒ Cache
constructor
see method for options description…
-
#keys ⇒ Object
List of keys.
-
#purge! ⇒ Object
gets rid of ALL keys in this cache…
-
#purge_expired! ⇒ Object
purge any expired keys…
Constructor Details
#initialize(options) ⇒ Cache
see method for options description… options are…
:file - sqlite3 file to use as persistence
:namespace - specify cache namespace (must be a string)
:expiration - number of seconds until keys expire
:timestamp_on_read - note the last time we touched a record...
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/sqlite3_cache.rb', line 14 def initialize() @OPTIONS = raise "Must supply :file!" unless @OPTIONS[:file] raise "Must supply :namespace!" unless @OPTIONS[:namespace] raise "Must supply :expiration" unless @OPTIONS[:expiration] @LOGGER = Logger.new(STDOUT) if @OPTIONS[:debug] @LOGGER.level = Logger::DEBUG else @LOGGER.level = Logger::WARN end unless @OPTIONS[:timestamp_on_read] == nil @OPTIONS[:timestamp_on_read] = false end begin @MUTEX = Mutex.new @SQLITE3 = SQLite3::Database.new(@OPTIONS[:file]) @SQLITE3.busy_timeout = 60000 rescue => e raise "Unable to open #{@OPTIONS[:file]}: #{e.message}" end end |
Instance Method Details
#[](key) ⇒ Object
retrieves a value from the cache
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/sqlite3_cache.rb', line 101 def [](key) @LOGGER.debug {"Retreiving key: #{key} for namespace: #{@OPTIONS[:namespace]}"} value = nil @MUTEX.synchronize do @SQLITE3.transaction do unless table_exists?(@OPTIONS[:namespace]) return nil end @SQLITE3.results_as_hash = true value = nil @SQLITE3.execute("SELECT * from #{@OPTIONS[:namespace]} where key = ?", key) do |row| value = Marshal.load(row["value"]) if value @LOGGER.debug {"Cache hit!"} else @LOGGER.debug {"Cache miss!"} end end end if @OPTIONS[:timestamp_on_read] # now update access time and count... @SQLITE3.execute("UPDATE #{@OPTIONS[:namespace]} SET accessed = ? where key = ?", Time.now.to_s, key) # retrieve count... access_count = nil @SQLITE3.execute("SELECT ACCESS_COUNT from #{@OPTIONS[:namespace]} where key = ?", key) do |row| access_count = row[0] end if access_count @SQLITE3.execute("UPDATE #{@OPTIONS[:namespace]} set access_count = ? where key = ?", access_count + 1, key) end end end return value end |
#[]=(key, value) ⇒ Object
sets a value in the cache
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/sqlite3_cache.rb', line 55 def []=(key, value) @LOGGER.debug {"Setting #{key} to #{value} for namespace: #{@OPTIONS[:namespace]}"} # make sure that table exists... table_init(@OPTIONS[:namespace]) # see if the key exists... existing_key = nil @MUTEX.synchronize do @SQLITE3.transaction do @SQLITE3.execute("select key from #{@OPTIONS[:namespace]} where key = ?", key) do |row| existing_key = row[0] end begin unless existing_key @SQLITE3.execute("insert into #{@OPTIONS[:namespace]} (key, created, value) values (?, ?, ?)", key, Time.now.to_s, Marshal.dump(value)) else @SQLITE3.execute("update #{@OPTIONS[:namespace]} set created = ?, value = ? where key = ?", Time.now.to_s, Marshal.dump(value), key) end rescue => e raise e end return value end end end |
#delete!(key) ⇒ Object
deletes a key from the cache
47 48 49 50 |
# File 'lib/sqlite3_cache.rb', line 47 def delete!(key) @LOGGER.debug {"Deleting #{key} from namespace #{@OPTIONS[:namespace]}"} @SQLITE3.execute("delete from #{@OPTIONS[:namespace]} where key = ?", key) end |
#each_pair(&block) ⇒ Object
iterate over each key and value in the namespace
152 153 154 155 156 157 158 159 |
# File 'lib/sqlite3_cache.rb', line 152 def each_pair(&block) @SQLITE3.results_as_hash = true @SQLITE3.execute("SELECT * from #{@OPTIONS[:namespace]}") do |row| key = row["key"] value = Marshal.load(row["value"]) yield key, value end end |
#exist?(key) ⇒ Boolean
checks to see if we have a given key…
83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/sqlite3_cache.rb', line 83 def exist?(key) @LOGGER.debug {"Checking for existence of key: #{key}"} @MUTEX.synchronize do @SQLITE3.transaction do unless table_exists?(@OPTIONS[:namespace]) return nil end end end @SQLITE3.execute("SELECT * from #{@OPTIONS[:namespace]} where key = ?", key) do |row| return true end return false end |
#expiration=(expiration) ⇒ Object
Returns the value that was passed in.
41 42 43 |
# File 'lib/sqlite3_cache.rb', line 41 def expiration=(expiration) @OPTIONS[:expiration] = expiration end |
#keys ⇒ Object
Returns list of keys.
162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/sqlite3_cache.rb', line 162 def keys @SQLITE3.results_as_hash = true keys = [] @SQLITE3.execute("SELECT key from #{@OPTIONS[:namespace]}") do |row| key = row["key"] if block_given? yield key else keys << key end end return keys end |
#purge! ⇒ Object
gets rid of ALL keys in this cache…
137 138 139 |
# File 'lib/sqlite3_cache.rb', line 137 def purge! @SQLITE3.execute("DROP TABLE #{@OPTIONS[:namespace]}") if table_exists?(@OPTIONS[:namespace]) end |
#purge_expired! ⇒ Object
purge any expired keys…
142 143 144 145 146 147 148 149 |
# File 'lib/sqlite3_cache.rb', line 142 def purge_expired! # okay, so see if any objects are older than # CURRENT_TIME - @OPTIONS[:expiration] expire_time = (Time.now - @OPTIONS[:expiration]).to_s if table_exists?(@OPTIONS[:namespace]) @SQLITE3.execute("DELETE FROM #{@OPTIONS[:namespace]} where created < ?", expire_time) end end |