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.
57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 57 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.
48 49 50 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 48 def path @path end |
Instance Method Details
#all ⇒ Array<Array>
Get all entries from the cache.
128 129 130 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 128 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.
118 119 120 121 122 123 124 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 118 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.
89 90 91 92 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 89 def delete(key) perform { _1.execute('DELETE FROM cache WHERE key = ?', [key]) } nil end |
#read(key) ⇒ Object?
Read a value from the cache.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 72 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) return unless value begin JSON.parse(Zlib::Inflate.inflate(value)) rescue Zlib::Error => e @loog.info("Failed to decompress cached value for key: #{key}, error: #{e.}, the key will be deleted") delete(key) end 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.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/fbe/middleware/sqlite_store.rb', line 100 def write(key, value) return if value.is_a?(Array) && value.any? do |vv| req = JSON.parse(vv[0]) req['method'] != 'get' end value = Zlib::Deflate.deflate(JSON.dump(value)) return if value.bytesize > @maxvsize perform do |t| t.execute(<<~SQL, [key, value, Time.now.utc.iso8601]) INSERT INTO cache(key, value, touched_at) VALUES(?1, ?2, ?3) ON CONFLICT(key) DO UPDATE SET value = ?2, touched_at = ?3 SQL end nil end |