Class: Kotoshu::Cache::BaseCache Abstract
- Inherits:
-
Object
- Object
- Kotoshu::Cache::BaseCache
- Defined in:
- lib/kotoshu/cache/base_cache.rb
Overview
Subclass must implement #download_resource, #load_cached
Abstract base class for all cache implementations.
Provides common functionality for:
-
HTTP downloads with metadata
-
Cache validation (exists, expired)
-
Statistics tracking (hits, misses, hit rate)
-
TTL management
Subclasses implement specific download and loading logic.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#cache_path ⇒ String
readonly
Path to the cache directory.
-
#cache_ttl ⇒ Integer
readonly
Cache TTL in seconds.
-
#github_url ⇒ String
readonly
GitHub repository URL.
-
#source_registry ⇒ Kotoshu::SourceRegistry
readonly
Single source of truth for per-repo URLs and pins.
-
#url_base ⇒ String
readonly
Base URL for downloading resources.
Instance Method Summary collapse
-
#available?(resource_id) ⇒ Boolean
Check if a resource is available in cache.
-
#cached_resources ⇒ Array<String>
List all cached resources.
-
#clean ⇒ Hash
Clean expired cache entries.
-
#clear(resource_id) ⇒ Boolean
Clear a specific resource from cache.
-
#clear_all ⇒ void
Clear all cached resources.
-
#download(resource_id) ⇒ Object?
Download a resource from GitHub.
-
#download_resource(resource_id, dest_path) ⇒ Object
abstract
Abstract: Download a specific resource.
-
#get(resource_id, force_download: false) ⇒ Object?
Get a resource from cache or download it.
-
#initialize(cache_path: nil, url_base: nil, cache_ttl: nil, github_url: nil, resource_pin: nil, manifest_url: nil, audit_log: nil, source_registry: nil) ⇒ BaseCache
constructor
Create a new cache.
-
#load_cached(resource_id) ⇒ Object?
abstract
Abstract: Load cached resource data.
-
#metadata_path_for(resource_id) ⇒ String
abstract
Abstract: Get metadata file path for a resource.
-
#reset_stats ⇒ self
Reset statistics counters.
-
#resource_dir_for(resource_id) ⇒ String
abstract
Abstract: Get resource directory path.
-
#resource_files_exist?(resource_id) ⇒ Boolean
abstract
Abstract: Check if all resource files exist.
-
#stats ⇒ Hash
Get cache statistics.
-
#supports_resource?(resource_id) ⇒ Boolean
Check if a resource type is supported.
Constructor Details
#initialize(cache_path: nil, url_base: nil, cache_ttl: nil, github_url: nil, resource_pin: nil, manifest_url: nil, audit_log: nil, source_registry: nil) ⇒ BaseCache
Create a new cache.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/kotoshu/cache/base_cache.rb', line 53 def initialize(cache_path: nil, url_base: nil, cache_ttl: nil, github_url: nil, resource_pin: nil, manifest_url: nil, audit_log: nil, source_registry: nil) @cache_path = cache_path || default_cache_path @source_registry = source_registry || default_source_registry @url_base = url_base || @source_registry.base_url @cache_ttl = cache_ttl || default_cache_ttl @github_url = github_url || default_github_url @resource_pin = resource_pin || @source_registry.pin_for_source(:spelling) @manifest_url = manifest_url @audit_log = audit_log || Kotoshu::Integrity::AuditLog.new @manifest = nil @manifest_loaded = false @hits = 0 @misses = 0 # Ensure cache directory exists FileUtils.mkdir_p(@cache_path) FileUtils.mkdir_p(File.join(@cache_path, "tmp")) end |
Instance Attribute Details
#cache_path ⇒ String (readonly)
Returns Path to the cache directory.
27 28 29 |
# File 'lib/kotoshu/cache/base_cache.rb', line 27 def cache_path @cache_path end |
#cache_ttl ⇒ Integer (readonly)
Returns Cache TTL in seconds.
33 34 35 |
# File 'lib/kotoshu/cache/base_cache.rb', line 33 def cache_ttl @cache_ttl end |
#github_url ⇒ String (readonly)
Returns GitHub repository URL.
36 37 38 |
# File 'lib/kotoshu/cache/base_cache.rb', line 36 def github_url @github_url end |
#source_registry ⇒ Kotoshu::SourceRegistry (readonly)
Returns Single source of truth for per-repo URLs and pins. Subclasses MUST build URLs through this registry rather than constructing URL strings inline.
41 42 43 |
# File 'lib/kotoshu/cache/base_cache.rb', line 41 def source_registry @source_registry end |
#url_base ⇒ String (readonly)
Returns Base URL for downloading resources.
30 31 32 |
# File 'lib/kotoshu/cache/base_cache.rb', line 30 def url_base @url_base end |
Instance Method Details
#available?(resource_id) ⇒ Boolean
Check if a resource is available in cache.
78 79 80 81 82 83 84 85 86 |
# File 'lib/kotoshu/cache/base_cache.rb', line 78 def available?(resource_id) return false unless supports_resource?(resource_id) = (resource_id) return false unless File.exist?() return false if expired?() resource_files_exist?(resource_id) end |
#cached_resources ⇒ Array<String>
List all cached resources.
177 178 179 |
# File 'lib/kotoshu/cache/base_cache.rb', line 177 def cached_resources raise NotImplementedError, "Subclass must implement" end |
#clean ⇒ Hash
Clean expired cache entries.
164 165 166 167 168 169 170 171 172 |
# File 'lib/kotoshu/cache/base_cache.rb', line 164 def clean expired_count = clean_expired size_reclaimed = clean_by_size { expired_entries_removed: expired_count, bytes_reclaimed: size_reclaimed } end |
#clear(resource_id) ⇒ Boolean
Clear a specific resource from cache.
111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/kotoshu/cache/base_cache.rb', line 111 def clear(resource_id) return false unless supports_resource?(resource_id) resource_dir = resource_dir_for(resource_id) if File.exist?(resource_dir) FileUtils.rm_rf(resource_dir) return true end false end |
#clear_all ⇒ void
This method returns an undefined value.
Clear all cached resources.
126 127 128 129 130 131 132 |
# File 'lib/kotoshu/cache/base_cache.rb', line 126 def clear_all @hits = 0 @misses = 0 FileUtils.rm_rf(@cache_path) FileUtils.mkdir_p(@cache_path) FileUtils.mkdir_p(File.join(@cache_path, "tmp")) end |
#download(resource_id) ⇒ Object?
Download a resource from GitHub.
193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/kotoshu/cache/base_cache.rb', line 193 def download(resource_id) return nil unless supports_resource?(resource_id) resource_dir = resource_dir_for(resource_id) FileUtils.mkdir_p(resource_dir) begin download_resource(resource_id, resource_dir) rescue StandardError => e warn "Error downloading #{resource_id}: #{e.}" if $VERBOSE nil end end |
#download_resource(resource_id, dest_path) ⇒ Object
Subclass must implement
Abstract: Download a specific resource.
213 214 215 |
# File 'lib/kotoshu/cache/base_cache.rb', line 213 def download_resource(resource_id, dest_path) raise NotImplementedError, "Subclass must implement" end |
#get(resource_id, force_download: false) ⇒ Object?
Get a resource from cache or download it.
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/kotoshu/cache/base_cache.rb', line 93 def get(resource_id, force_download: false) return nil unless supports_resource?(resource_id) = (resource_id) if !force_download && cached?() && !expired?() @hits += 1 return load_cached(resource_id) end @misses += 1 download(resource_id) end |
#load_cached(resource_id) ⇒ Object?
Subclass must implement
Abstract: Load cached resource data.
222 223 224 |
# File 'lib/kotoshu/cache/base_cache.rb', line 222 def load_cached(resource_id) raise NotImplementedError, "Subclass must implement" end |
#metadata_path_for(resource_id) ⇒ String
Subclass must implement
Abstract: Get metadata file path for a resource.
231 232 233 |
# File 'lib/kotoshu/cache/base_cache.rb', line 231 def (resource_id) raise NotImplementedError, "Subclass must implement" end |
#reset_stats ⇒ self
Reset statistics counters.
155 156 157 158 159 |
# File 'lib/kotoshu/cache/base_cache.rb', line 155 def reset_stats @hits = 0 @misses = 0 self end |
#resource_dir_for(resource_id) ⇒ String
Subclass must implement
Abstract: Get resource directory path.
240 241 242 |
# File 'lib/kotoshu/cache/base_cache.rb', line 240 def resource_dir_for(resource_id) raise NotImplementedError, "Subclass must implement" end |
#resource_files_exist?(resource_id) ⇒ Boolean
Subclass must implement
Abstract: Check if all resource files exist.
249 250 251 |
# File 'lib/kotoshu/cache/base_cache.rb', line 249 def resource_files_exist?(resource_id) raise NotImplementedError, "Subclass must implement" end |
#stats ⇒ Hash
Get cache statistics.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/kotoshu/cache/base_cache.rb', line 137 def stats total = @hits + @misses hit_rate = total.positive? ? (@hits.to_f / total) : 0.0 { hits: @hits, misses: @misses, total: total, hit_rate: hit_rate, cached_resources: cached_resources, size_bytes: cache_size, oldest_entry: oldest_entry } end |
#supports_resource?(resource_id) ⇒ Boolean
Check if a resource type is supported.
185 186 187 |
# File 'lib/kotoshu/cache/base_cache.rb', line 185 def supports_resource?(resource_id) raise NotImplementedError, "Subclass must implement" end |