Class: RubynCode::Tools::FileCache

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyn_code/tools/file_cache.rb

Overview

Session-scoped file cache that serves previously-read file contents when the file has not been modified since the last read. Invalidates automatically when Rubyn writes or edits a file, or when mtime changes.

Defined Under Namespace

Classes: Entry

Constant Summary collapse

CHARS_PER_TOKEN =
4

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFileCache

Returns a new instance of FileCache.



15
16
17
# File 'lib/rubyn_code/tools/file_cache.rb', line 15

def initialize
  @cache = {}
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



13
14
15
# File 'lib/rubyn_code/tools/file_cache.rb', line 13

def cache
  @cache
end

Instance Method Details

#cached?(path) ⇒ Boolean

Returns true if the given path is currently cached and fresh.

Returns:

  • (Boolean)


53
54
55
56
57
58
59
60
# File 'lib/rubyn_code/tools/file_cache.rb', line 53

def cached?(path)
  return false unless @cache.key?(path)

  @cache[path].mtime == File.mtime(path)
rescue Errno::ENOENT
  @cache.delete(path)
  false
end

#clear!Object

Clears the entire cache.



63
64
65
# File 'lib/rubyn_code/tools/file_cache.rb', line 63

def clear!
  @cache.clear
end

#invalidate(path) ⇒ Object

Removes a path from the cache. Called when Rubyn writes/edits the file.



43
44
45
# File 'lib/rubyn_code/tools/file_cache.rb', line 43

def invalidate(path)
  @cache.delete(path)
end

#on_write(path) ⇒ Object

Alias for use as a write hook.



48
49
50
# File 'lib/rubyn_code/tools/file_cache.rb', line 48

def on_write(path)
  invalidate(path)
end

#read(path) ⇒ Hash

Returns cached content if the file hasn’t changed, otherwise reads from disk and caches the result.

Parameters:

  • path (String)

    absolute file path

Returns:

  • (Hash)

    { content:, source: :cache|:disk, tokens_saved: }



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rubyn_code/tools/file_cache.rb', line 24

def read(path)
  current_mtime = File.mtime(path)
  cached = @cache[path]

  if cached && cached.mtime == current_mtime
    bump_hits(path)
    { content: cached.content, source: :cache, tokens_saved: cached.token_count }
  else
    content = File.read(path)
    token_count = estimate_tokens(content)
    @cache[path] = Entry.new(
      content: content, mtime: current_mtime,
      token_count: token_count, read_count: 1, cache_hits: 0
    )
    { content: content, source: :disk, tokens_saved: 0 }
  end
end

#statsObject

Returns aggregate statistics about cache performance.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rubyn_code/tools/file_cache.rb', line 68

def stats
  total_reads = @cache.values.sum(&:read_count)
  total_hits = @cache.values.sum(&:cache_hits)
  tokens_saved = @cache.values.sum { |e| e.cache_hits * e.token_count }
  hit_rate = total_reads.positive? ? total_hits.to_f / (total_reads + total_hits) : 0.0

  {
    entries: @cache.size,
    total_reads: total_reads,
    cache_hits: total_hits,
    hit_rate: hit_rate.round(3),
    tokens_saved: tokens_saved
  }
end