Class: Fbe::Middleware::SqliteStore
- Inherits:
-
Object
- Object
- Fbe::Middleware::SqliteStore
- Defined in:
- lib/fbe/middleware/sqlite_store.rb
Overview
Persisted SQLite store for Faraday::HttpCache
This class provides a persistent cache store backed by SQLite for use with Faraday::HttpCache middleware. It’s designed to cache HTTP responses from GitHub API calls to reduce API rate limit consumption and improve performance.
Key features:
-
Automatic version management to invalidate cache on version changes
-
Size-based cache eviction (configurable, defaults to 10MB)
-
Thread-safe SQLite transactions
-
JSON serialization for cached values
-
Filtering of non-cacheable requests (non-GET, URLs with query parameters)
Usage example:
store = Fbe::Middleware::SqliteStore.new(
'/path/to/cache.db',
'1.0.0',
loog: logger,
maxsize: '50Mb'
)
# Use with Faraday
Faraday.new do |builder|
builder.use Faraday::HttpCache, store: store
end
The store automatically manages the SQLite database schema and handles cleanup operations when the database grows too large. Old entries are deleted based on their last access time to maintain the configured size limit.
- Author
-
Yegor Bugayenko ([email protected])
- Copyright
-
Copyright © 2024-2025 Zerocracy
- License
-
MIT
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Instance Method Summary collapse
-
#all ⇒ Array<Array>
Get all entries from the cache.
-
#clear ⇒ void
Clear all entries from the cache.
-
#delete(key) ⇒ nil
Delete a key from the cache.
-
#initialize(path, version, loog: Loog::NULL, maxsize: '10Mb', maxvsize: '10Kb') ⇒ SqliteStore
constructor
Initialize the SQLite store.
-
#read(key) ⇒ Object?
Read a value from the cache.
-
#write(key, value) ⇒ nil
Write a value to the cache.
Constructor Details
#initialize(path, version, loog: Loog::NULL, maxsize: '10Mb', maxvsize: '10Kb') ⇒ SqliteStore
Initialize the SQLite store.
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 56 def initialize(path, version, loog: Loog::NULL, maxsize: '10Mb', maxvsize: '10Kb') raise ArgumentError, 'Database path cannot be nil or empty' if path.nil? || path.empty? dir = File.dirname(path) raise ArgumentError, "Directory #{dir} does not exist" unless File.directory?(dir) raise ArgumentError, 'Version cannot be nil or empty' if version.nil? || version.empty? @path = File.absolute_path(path) @version = version @loog = loog @maxsize = Filesize.from(maxsize.to_s).to_i @maxvsize = Filesize.from(maxvsize.to_s).to_i end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
47 48 49 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 47 def path @path end |
Instance Method Details
#all ⇒ Array<Array>
Get all entries from the cache.
121 122 123 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 121 def all perform { _1.execute('SELECT key, value FROM cache') } end |
#clear ⇒ void
This method returns an undefined value.
Clear all entries from the cache.
111 112 113 114 115 116 117 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 111 def clear perform do |t| t.execute 'DELETE FROM cache;' t.execute "UPDATE meta SET value = ? WHERE key = 'version';", [@version] end @db.execute 'VACUUM;' end |
#delete(key) ⇒ nil
Delete a key from the cache.
82 83 84 85 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 82 def delete(key) perform { _1.execute('DELETE FROM cache WHERE key = ?', [key]) } nil end |
#read(key) ⇒ Object?
Read a value from the cache.
71 72 73 74 75 76 77 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 71 def read(key) value = perform do |t| t.execute('UPDATE cache SET touched_at = ?2 WHERE key = ?1;', [key, Time.now.utc.iso8601]) t.execute('SELECT value FROM cache WHERE key = ? LIMIT 1;', [key]) end.dig(0, 0) JSON.parse(value) if value end |
#write(key, value) ⇒ nil
Values larger than 10KB are not cached
Non-GET requests and URLs with query parameters are not cached
Write a value to the cache.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 93 def write(key, value) return if value.is_a?(Array) && value.any? do |vv| req = JSON.parse(vv[0]) req['method'] != 'get' end value = JSON.dump(value) return if value.bytesize > @maxvsize perform do |t| t.execute(" INSERT INTO cache(key, value, touched_at) VALUES(?1, ?2, ?3)\n ON CONFLICT(key) DO UPDATE SET value = ?2, touched_at = ?3\n SQL\n end\n nil\nend\n", [key, value, Time.now.utc.iso8601]) |