Class: Ace::Compressor::Molecules::CacheStore

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/compressor/molecules/cache_store.rb

Constant Summary collapse

PACK_EXTENSION =
".pack"
METADATA_EXTENSION =
".json"
SHORT_KEY_LENGTH =
12
EXACT_CACHE_CONTRACT =
"exact-list-shell-v3"
COMPACT_CACHE_CONTRACT =
"compact-list-shell-v3"
AGENT_CACHE_CONTRACT =
"agent-payload-rewrite-v7"

Instance Method Summary collapse

Constructor Details

#initialize(cache_root: nil, project_root: Dir.pwd) ⇒ CacheStore

Returns a new instance of CacheStore.



19
20
21
22
# File 'lib/ace/compressor/molecules/cache_store.rb', line 19

def initialize(cache_root: nil, project_root: Dir.pwd)
  @cache_root = File.expand_path(cache_root || default_cache_root, project_root)
  @project_root = File.expand_path(project_root)
end

Instance Method Details

#cache_hit?(pack_path:, metadata_path:) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
# File 'lib/ace/compressor/molecules/cache_store.rb', line 119

def cache_hit?(pack_path:, metadata_path:)
  File.file?(pack_path) && File.file?()
end

#canonical_paths(mode:, sources:, manifest_key:) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/ace/compressor/molecules/cache_store.rb', line 52

def canonical_paths(mode:, sources:, manifest_key:)
  relative_stem = default_stem_for(sources)
  short_key = manifest_key[0, SHORT_KEY_LENGTH]
  pack_path = File.join(@cache_root, mode, "#{relative_stem}.#{short_key}.#{mode}#{PACK_EXTENSION}")

  {
    pack_path: pack_path,
    metadata_path: pack_path.sub(/#{Regexp.escape(PACK_EXTENSION)}\z/o, METADATA_EXTENSION),
    short_key: short_key
  }
end

#manifest(mode:, sources:) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ace/compressor/molecules/cache_store.rb', line 24

def manifest(mode:, sources:)
  source_entries = Array(sources).map { |source| normalize_source_entry(source) }
    .sort_by { |entry| entry.fetch("path") }
    .map do |entry|
      content = File.binread(entry.fetch("content_path"))
      {
        "path" => entry.fetch("path"),
        "sha256" => Digest::SHA256.hexdigest(content),
        "bytes" => content.bytesize,
        "lines" => line_count(content)
      }
  end

  payload = {
    "schema" => Ace::Compressor::Models::ContextPack::SCHEMA,
    "mode" => mode,
    "sources" => source_entries
  }
  payload["mode_contract"] = mode_contract_for(mode)

  {
    "key" => Digest::SHA256.hexdigest(JSON.generate(payload)),
    "sources" => source_entries,
    "original_bytes" => source_entries.sum { |entry| entry["bytes"] },
    "original_lines" => source_entries.sum { |entry| entry["lines"] }
  }
end

#output_path_for(output:, mode:, sources:, manifest_key:) ⇒ Object



109
110
111
112
113
114
115
116
117
# File 'lib/ace/compressor/molecules/cache_store.rb', line 109

def output_path_for(output:, mode:, sources:, manifest_key:)
  paths = canonical_paths(mode: mode, sources: sources, manifest_key: manifest_key)
  return paths[:pack_path] if output.nil? || output.to_s.strip.empty?

  expanded = File.expand_path(output)
  return directory_output_path(expanded, paths[:short_key], mode, sources) if directory_target?(output, expanded)

  expanded
end

#read_metadata(metadata_path) ⇒ Object



127
128
129
# File 'lib/ace/compressor/molecules/cache_store.rb', line 127

def ()
  JSON.parse(File.read())
end

#read_pack(pack_path) ⇒ Object



123
124
125
# File 'lib/ace/compressor/molecules/cache_store.rb', line 123

def read_pack(pack_path)
  File.read(pack_path)
end

#shared_cache_eligible?(sources) ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
71
72
73
74
# File 'lib/ace/compressor/molecules/cache_store.rb', line 68

def shared_cache_eligible?(sources)
  return false unless shared_cache_enabled?
  return false unless shared_cache_scope == "workflow_only"

  values = Array(sources)
  values.size == 1 && workflow_source?(values.first)
end

#shared_cache_enabled?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/ace/compressor/molecules/cache_store.rb', line 64

def shared_cache_enabled?
  !shared_cache_root.to_s.strip.empty?
end

#shared_canonical_paths(mode:, sources:, manifest_key:) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ace/compressor/molecules/cache_store.rb', line 94

def shared_canonical_paths(mode:, sources:, manifest_key:)
  return nil unless shared_cache_eligible?(sources)

  source = normalize_source_entry(Array(sources).first)
  stem = shared_stem_for(source)
  short_key = manifest_key[0, SHORT_KEY_LENGTH]
  pack_path = File.join(shared_cache_root, mode, "#{stem}.#{short_key}.#{mode}#{PACK_EXTENSION}")

  {
    pack_path: pack_path,
    metadata_path: pack_path.sub(/#{Regexp.escape(PACK_EXTENSION)}\z/o, METADATA_EXTENSION),
    short_key: short_key
  }
end

#shared_manifest(mode:, sources:) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/ace/compressor/molecules/cache_store.rb', line 76

def shared_manifest(mode:, sources:)
  return nil unless shared_cache_eligible?(sources)

  source = normalize_source_entry(Array(sources).first)
  content = File.binread(source.fetch("content_path"))
  payload = {
    "schema" => Ace::Compressor::Models::ContextPack::SCHEMA,
    "mode" => mode,
    "mode_contract" => mode_contract_for(mode),
    "source_kind" => "workflow",
    "sha256" => Digest::SHA256.hexdigest(content),
    "bytes" => content.bytesize,
    "lines" => line_count(content)
  }

  {"key" => Digest::SHA256.hexdigest(JSON.generate(payload))}
end

#stats_block(mode:, cache_hit:, output_path:, metadata:) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/ace/compressor/molecules/cache_store.rb', line 143

def stats_block(mode:, cache_hit:, output_path:, metadata:)
  [
    "Cache:    #{cache_hit ? "hit" : "miss"}",
    "Output:   #{output_path}",
    "Sources:  #{file_label(.fetch("file_count"))}",
    "Mode:     #{mode}",
    "Original: #{format_bytes(.fetch("original_bytes"))}, #{line_label(.fetch("original_lines"))}",
    "Packed:   #{format_bytes(.fetch("packed_bytes"))}, #{line_label(.fetch("packed_lines"))}",
    "Change:   #{format_change(.fetch("original_bytes"), .fetch("packed_bytes"), "bytes")}, #{format_change(.fetch("original_lines"), .fetch("packed_lines"), "lines")}"
  ].join("\n")
end

#write_cache(pack_path:, metadata_path:, content:, metadata:) ⇒ Object



131
132
133
134
135
136
# File 'lib/ace/compressor/molecules/cache_store.rb', line 131

def write_cache(pack_path:, metadata_path:, content:, metadata:)
  ensure_parent_dir(pack_path)
  ensure_parent_dir()
  File.write(pack_path, content)
  File.write(, JSON.pretty_generate())
end

#write_output(output_path, content) ⇒ Object



138
139
140
141
# File 'lib/ace/compressor/molecules/cache_store.rb', line 138

def write_output(output_path, content)
  ensure_parent_dir(output_path)
  File.write(output_path, content)
end