Class: Litecache
- Inherits:
-
Object
- Object
- Litecache
- Defined in:
- lib/litestack/litecache.rb
Overview
Litecache is a caching library for Ruby applications that is built on top of SQLite. It is designed to be simple to use, very fast, and feature-rich, providing developers with a reliable and efficient way to cache data.
One of the main features of Litecache is automatic key expiry, which allows developers to set an expiration time for each cached item. This ensures that cached data is automatically removed from the cache after a certain amount of time has passed, reducing the risk of stale data being served to users.
In addition, Litecache supports LRU (Least Recently Used) removal, which means that if the cache reaches its capacity limit, the least recently used items will be removed first to make room for new items. This ensures that the most frequently accessed data is always available in the cache.
Litecache also supports integer value increment/decrement, which allows developers to increment or decrement the value of a cached item in a thread-safe manner. This is useful for implementing counters or other types of numerical data that need to be updated frequently.
Overall, Litecache is a powerful and flexible caching library that provides automatic key expiry, LRU removal, and integer value increment/decrement capabilities. Its fast performance and simple API make it an excellent choice for Ruby applications that need a reliable and efficient way to cache data.
Constant Summary collapse
- DEFAULT_OPTIONS =
the default options for the cache can be overriden by passing new options in a hash to Litecache.new
path: "./cache.db" expiry: 60 * 60 * 24 * 30 -> one month default expiry if none is provided size: 128 * 1024 * 1024 -> 128MB mmap_size: 128 * 1024 * 1024 -> 128MB to be held in memory min_size: 32 * 1024 -> 32MB return_full_record: false -> only return the payload sleep_interval: 1 -> 1 second of sleep between cleanup runs { path: Litesupport.root.join("cache.sqlite3"), config_path: "./litecache.yml", sync: 0, expiry: 60 * 60 * 24 * 30, # one month size: 128 * 1024 * 1024, # 128MB mmap_size: 128 * 1024 * 1024, # 128MB min_size: 8 * 1024 * 1024, # 16MB return_full_record: false, # only return the payload sleep_interval: 1, # 1 second metrics: false }
Instance Method Summary collapse
-
#clear ⇒ Object
delete all key, value pairs in the cache.
-
#close ⇒ Object
close the connection to the cache file.
-
#count ⇒ Object
return the number of key, value pairs in the cache.
-
#decrement(key, amount, expires_in = nil) ⇒ Object
decrement an integer value by amount, optionally add an expiry value (in seconds).
-
#delete(key) ⇒ Object
delete a key, value pair from the cache.
-
#get(key) ⇒ Object
get a value by its key if the key doesn’t exist or it is expired then null will be returned.
-
#increment(key, amount, expires_in = nil) ⇒ Object
increment an integer value by amount, optionally add an expiry value (in seconds).
-
#initialize(options = {}) ⇒ Litecache
constructor
creates a new instance of Litecache can optionally receive an options hash which will be merged with the DEFAULT_OPTIONS (the new hash overrides any matching keys in the default one).
-
#max_size ⇒ Object
return the maximum size of the cache.
-
#prune(limit = nil) ⇒ Object
delete all entries in the cache up limit (ordered by LRU), if no limit is provided approximately 20% of the entries will be deleted.
-
#set(key, value, expires_in = nil) ⇒ Object
add a key, value pair to the cache, with an optional expiry value (number of seconds).
-
#set_unless_exists(key, value, expires_in = nil) ⇒ Object
add a key, value pair to the cache, but only if the key doesn’t exist, with an optional expiry value (number of seconds).
- #snapshot ⇒ Object
-
#transaction(mode, acquire = true) ⇒ Object
low level access to SQLite transactions, use with caution.
Methods included from Litemetric::Measurable
#capture, #capture_snapshot, #collect_metrics, #create_snapshotter, #measure, #metrics_identifier
Methods included from Litesupport::Liteconnection
#journal_mode, #options, #path, #size, #synchronous
Methods included from Litesupport::Forkable
Constructor Details
#initialize(options = {}) ⇒ Litecache
creates a new instance of Litecache can optionally receive an options hash which will be merged with the DEFAULT_OPTIONS (the new hash overrides any matching keys in the default one).
Example:
litecache = Litecache.new
litecache.set("a", "somevalue")
litecache.get("a") # => "somevalue"
litecache.set("b", "othervalue", 1) # expire aftre 1 second
litecache.get("b") # => "othervalue"
sleep 2
litecache.get("b") # => nil
litecache.clear # nothing remains in the cache
litecache.close # optional, you can safely kill the process
64 65 66 67 68 69 |
# File 'lib/litestack/litecache.rb', line 64 def initialize( = {}) [:size] = DEFAULT_OPTIONS[:min_size] if [:size] && [:size] < DEFAULT_OPTIONS[:min_size] @last_visited = {} init() collect_metrics if @options[:metrics] end |
Instance Method Details
#clear ⇒ Object
delete all key, value pairs in the cache
163 164 165 |
# File 'lib/litestack/litecache.rb', line 163 def clear run_sql("delete FROM data") end |
#close ⇒ Object
close the connection to the cache file
168 169 170 171 |
# File 'lib/litestack/litecache.rb', line 168 def close @running = false super end |
#count ⇒ Object
return the number of key, value pairs in the cache
153 154 155 |
# File 'lib/litestack/litecache.rb', line 153 def count run_stmt(:counter)[0][0] end |
#decrement(key, amount, expires_in = nil) ⇒ Object
decrement an integer value by amount, optionally add an expiry value (in seconds)
135 136 137 |
# File 'lib/litestack/litecache.rb', line 135 def decrement(key, amount, expires_in = nil) increment(key, -amount, expires_in) end |
#delete(key) ⇒ Object
delete a key, value pair from the cache
119 120 121 122 123 124 125 126 |
# File 'lib/litestack/litecache.rb', line 119 def delete(key) changes = 0 @conn.acquire do |cache| cache.stmts[:deleter].execute!(key) changes = cache.changes end changes > 0 end |
#get(key) ⇒ Object
get a value by its key if the key doesn’t exist or it is expired then null will be returned
107 108 109 110 111 112 113 114 115 116 |
# File 'lib/litestack/litecache.rb', line 107 def get(key) key = key.to_s if (record = @conn.acquire { |cache| cache.stmts[:getter].execute!(key)[0] }) @last_visited[key] = true capture(:get, key, 1) return record[1] end capture(:get, key, 0) nil end |
#increment(key, amount, expires_in = nil) ⇒ Object
increment an integer value by amount, optionally add an expiry value (in seconds)
129 130 131 132 |
# File 'lib/litestack/litecache.rb', line 129 def increment(key, amount, expires_in = nil) expires_in ||= @expires_in @conn.acquire { |cache| cache.stmts[:incrementer].execute!(key.to_s, amount, expires_in) } end |
#max_size ⇒ Object
return the maximum size of the cache
174 175 176 |
# File 'lib/litestack/litecache.rb', line 174 def max_size run_sql("SELECT s.page_size * c.max_page_count FROM pragma_page_size() as s, pragma_max_page_count() as c")[0][0].to_f / (1024 * 1024) end |
#prune(limit = nil) ⇒ Object
delete all entries in the cache up limit (ordered by LRU), if no limit is provided approximately 20% of the entries will be deleted
140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/litestack/litecache.rb', line 140 def prune(limit = nil) @conn.acquire do |cache| if limit&.is_a? Integer cache.stmts[:limited_pruner].execute!(limit) elsif limit&.is_a? Float cache.stmts[:extra_pruner].execute!(limit) else cache.stmts[:pruner].execute! end end end |
#set(key, value, expires_in = nil) ⇒ Object
add a key, value pair to the cache, with an optional expiry value (number of seconds)
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/litestack/litecache.rb', line 72 def set(key, value, expires_in = nil) key = key.to_s expires_in = @options[:expires_in] if expires_in.nil? || expires_in.zero? @conn.acquire do |cache| cache.stmts[:setter].execute!(key, value, expires_in) capture(:set, key) rescue SQLite3::FullException cache.stmts[:extra_pruner].execute!(0.2) cache.execute("vacuum") retry end true end |
#set_unless_exists(key, value, expires_in = nil) ⇒ Object
add a key, value pair to the cache, but only if the key doesn’t exist, with an optional expiry value (number of seconds)
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/litestack/litecache.rb', line 87 def set_unless_exists(key, value, expires_in = nil) key = key.to_s expires_in = @options[:expires_in] if expires_in.nil? || expires_in.zero? changes = 0 @conn.acquire do |cache| cache.transaction(:immediate) do cache.stmts[:inserter].execute!(key, value, expires_in) changes = cache.changes end capture(:set, key) rescue SQLite3::FullException cache.stmts[:extra_pruner].execute!(0.2) cache.execute("vacuum") retry end changes > 0 end |
#snapshot ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/litestack/litecache.rb', line 178 def snapshot { summary: { path: path, journal_mode: journal_mode, synchronous: synchronous, size: size, max_size: max_size, entries: count } } end |
#transaction(mode, acquire = true) ⇒ Object
low level access to SQLite transactions, use with caution
192 193 194 195 196 197 198 199 |
# File 'lib/litestack/litecache.rb', line 192 def transaction(mode, acquire = true) return cache.transaction(mode) { yield } unless acquire @conn.acquire do |cache| cache.transaction(mode) do yield end end end |