Class: Kotoshu::Cache::BaseCache Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/kotoshu/cache/base_cache.rb

Overview

This class is abstract.

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

FrequencyCache, LanguageCache, ModelCache

Instance Attribute Summary collapse

Instance Method Summary collapse

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.

Parameters:

  • cache_path (String) (defaults to: nil)

    Path to cache directory

  • url_base (String) (defaults to: nil)

    Base URL for downloads (deprecated; pass source_registry instead)

  • cache_ttl (Integer) (defaults to: nil)

    Cache TTL in seconds

  • github_url (String) (defaults to: nil)

    GitHub repository URL

  • resource_pin (String) (defaults to: nil)

    Branch/tag/commit for URL templates (deprecated; use source_registry)

  • manifest_url (String, nil) (defaults to: nil)

    Override manifest.json URL

  • audit_log (Integrity::AuditLog, nil) (defaults to: nil)

    Override audit log

  • source_registry (Kotoshu::SourceRegistry, nil) (defaults to: nil)

    Single source of truth for URLs/pins



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_pathString (readonly)

Returns Path to the cache directory.

Returns:

  • (String)

    Path to the cache directory



27
28
29
# File 'lib/kotoshu/cache/base_cache.rb', line 27

def cache_path
  @cache_path
end

#cache_ttlInteger (readonly)

Returns Cache TTL in seconds.

Returns:

  • (Integer)

    Cache TTL in seconds



33
34
35
# File 'lib/kotoshu/cache/base_cache.rb', line 33

def cache_ttl
  @cache_ttl
end

#github_urlString (readonly)

Returns GitHub repository URL.

Returns:

  • (String)

    GitHub repository URL



36
37
38
# File 'lib/kotoshu/cache/base_cache.rb', line 36

def github_url
  @github_url
end

#source_registryKotoshu::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.

Returns:

  • (Kotoshu::SourceRegistry)

    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_baseString (readonly)

Returns Base URL for downloading resources.

Returns:

  • (String)

    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.

Parameters:

  • resource_id (String)

    The resource identifier (e.g., language code)

Returns:

  • (Boolean)

    True if resource is cached and valid



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_resourcesArray<String>

List all cached resources.

Returns:

  • (Array<String>)

    List of cached resource identifiers

Raises:

  • (NotImplementedError)


177
178
179
# File 'lib/kotoshu/cache/base_cache.rb', line 177

def cached_resources
  raise NotImplementedError, "Subclass must implement"
end

#cleanHash

Clean expired cache entries.

Returns:

  • (Hash)

    Cleanup statistics



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.

Parameters:

  • resource_id (String)

    The resource identifier

Returns:

  • (Boolean)

    True if cache was cleared



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_allvoid

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.

Parameters:

  • resource_id (String)

    The resource identifier

Returns:

  • (Object, nil)

    Downloaded resource or nil on error



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.message}" if $VERBOSE
    nil
  end
end

#download_resource(resource_id, dest_path) ⇒ Object

This method is abstract.

Subclass must implement

Abstract: Download a specific resource.

Parameters:

  • resource_id (String)

    The resource identifier

  • dest_path (String)

    Destination directory

Returns:

  • (Object)

    Downloaded resource

Raises:

  • (NotImplementedError)


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.

Parameters:

  • resource_id (String)

    The resource identifier

  • force_download (Boolean) (defaults to: false)

    Force re-download even if cached

Returns:

  • (Object, nil)

    The cached resource or nil if not available



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?

This method is abstract.

Subclass must implement

Abstract: Load cached resource data.

Parameters:

  • resource_id (String)

    The resource identifier

Returns:

  • (Object, nil)

    Loaded resource or nil

Raises:

  • (NotImplementedError)


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

This method is abstract.

Subclass must implement

Abstract: Get metadata file path for a resource.

Parameters:

  • resource_id (String)

    The resource identifier

Returns:

  • (String)

    Metadata file path

Raises:

  • (NotImplementedError)


231
232
233
# File 'lib/kotoshu/cache/base_cache.rb', line 231

def (resource_id)
  raise NotImplementedError, "Subclass must implement"
end

#reset_statsself

Reset statistics counters.

Returns:

  • (self)

    Self for chaining



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

This method is abstract.

Subclass must implement

Abstract: Get resource directory path.

Parameters:

  • resource_id (String)

    The resource identifier

Returns:

  • (String)

    Resource directory path

Raises:

  • (NotImplementedError)


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

This method is abstract.

Subclass must implement

Abstract: Check if all resource files exist.

Parameters:

  • resource_id (String)

    The resource identifier

Returns:

  • (Boolean)

    True if all files exist

Raises:

  • (NotImplementedError)


249
250
251
# File 'lib/kotoshu/cache/base_cache.rb', line 249

def resource_files_exist?(resource_id)
  raise NotImplementedError, "Subclass must implement"
end

#statsHash

Get cache statistics.

Returns:

  • (Hash)

    Statistics including :hits, :misses, :hit_rate, :size



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.

Parameters:

  • resource_id (String)

    The resource identifier

Returns:

  • (Boolean)

    True if supported

Raises:

  • (NotImplementedError)


185
186
187
# File 'lib/kotoshu/cache/base_cache.rb', line 185

def supports_resource?(resource_id)
  raise NotImplementedError, "Subclass must implement"
end