Class: Tina4::CacheBackends::FileBackend
- Inherits:
-
BaseBackend
- Object
- BaseBackend
- Tina4::CacheBackends::FileBackend
- Defined in:
- lib/tina4/cache_backends/file_backend.rb
Overview
File-based cache — stores entries as JSON files in data/cache/ (parity with Python _FileBackend). Always available; used as the graceful-degrade target when a configured network backend is unreachable.
Instance Method Summary collapse
- #clear ⇒ Object
- #delete(key) ⇒ Object
- #get(key) ⇒ Object
-
#initialize(cache_dir: "data/cache", max_entries: 1000) ⇒ FileBackend
constructor
A new instance of FileBackend.
- #name ⇒ Object
- #set(key, value, ttl) ⇒ Object
- #stats ⇒ Object
-
#sweep ⇒ Integer
Actively delete expired entries and return the number removed.
Methods inherited from BaseBackend
Constructor Details
#initialize(cache_dir: "data/cache", max_entries: 1000) ⇒ FileBackend
Returns a new instance of FileBackend.
14 15 16 17 18 19 20 21 |
# File 'lib/tina4/cache_backends/file_backend.rb', line 14 def initialize(cache_dir: "data/cache", max_entries: 1000) @dir = cache_dir @max_entries = max_entries @mutex = Mutex.new @hits = 0 @misses = 0 FileUtils.mkdir_p(@dir) end |
Instance Method Details
#clear ⇒ Object
78 79 80 81 82 83 84 |
# File 'lib/tina4/cache_backends/file_backend.rb', line 78 def clear @mutex.synchronize do @hits = 0 @misses = 0 Dir.glob(File.join(@dir, "*.json")).each { |f| File.delete(f) rescue nil } end end |
#delete(key) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/tina4/cache_backends/file_backend.rb', line 66 def delete(key) path = key_path(key) @mutex.synchronize do if File.exist?(path) File.delete(path) rescue nil true else false end end end |
#get(key) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/tina4/cache_backends/file_backend.rb', line 23 def get(key) path = key_path(key) @mutex.synchronize do unless File.exist?(path) @misses += 1 return nil end begin data = JSON.parse(File.read(path)) expires_at = data["expires_at"] if expires_at && Time.now.to_f > expires_at File.delete(path) rescue nil @misses += 1 return nil end @hits += 1 data["value"] rescue JSON::ParserError, SystemCallError @misses += 1 nil end end end |
#name ⇒ Object
106 107 108 |
# File 'lib/tina4/cache_backends/file_backend.rb', line 106 def name "file" end |
#set(key, value, ttl) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/tina4/cache_backends/file_backend.rb', line 47 def set(key, value, ttl) expires_at = ttl > 0 ? Time.now.to_f + ttl : nil entry = { "key" => key, "value" => value, "expires_at" => expires_at } @mutex.synchronize do FileUtils.mkdir_p(@dir) begin files = Dir.glob(File.join(@dir, "*.json")).sort_by { |f| File.mtime(f) } while files.size >= @max_entries File.delete(files.shift) rescue nil end rescue SystemCallError end begin File.write(key_path(key), JSON.generate(entry)) rescue SystemCallError end end end |
#stats ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/tina4/cache_backends/file_backend.rb', line 86 def stats @mutex.synchronize do now = Time.now.to_f count = 0 Dir.glob(File.join(@dir, "*.json")).each do |f| begin data = JSON.parse(File.read(f)) exp = data["expires_at"] if exp && now > exp File.delete(f) rescue nil else count += 1 end rescue JSON::ParserError, SystemCallError end end { hits: @hits, misses: @misses, size: count, backend: "file" } end end |
#sweep ⇒ Integer
Actively delete expired entries and return the number removed. (The file backend is the only one that supports an explicit sweep —network/db backends expire lazily via TTL.)
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/tina4/cache_backends/file_backend.rb', line 115 def sweep removed = 0 now = Time.now.to_f @mutex.synchronize do Dir.glob(File.join(@dir, "*.json")).each do |f| begin data = JSON.parse(File.read(f)) if data["expires_at"] && now > data["expires_at"] File.delete(f) rescue nil removed += 1 end rescue JSON::ParserError, SystemCallError end end end removed end |