Class: Rwm::TaskCache
- Inherits:
-
Object
- Object
- Rwm::TaskCache
- Defined in:
- lib/rwm/task_cache.rb
Instance Method Summary collapse
-
#cache_declarations(package) ⇒ Object
Discover cacheable task declarations by running ‘bundle exec rake rwm:cache_config`.
-
#cacheable?(package, task) ⇒ Boolean
Returns true if the task is declared cacheable in the package’s Rakefile.
-
#cached?(package, task) ⇒ Boolean
Returns true if the (package, task) pair is cached and inputs haven’t changed.
-
#content_hash(package) ⇒ Object
Compute a content hash for a package: SHA256 of all source files + dependency hashes.
-
#initialize(workspace, graph) ⇒ TaskCache
constructor
A new instance of TaskCache.
-
#outputs_exist?(package, output_pattern) ⇒ Boolean
Check if declared output files/globs exist in the package directory.
-
#store(package, task) ⇒ Object
Store the current content hash after a successful task run.
Constructor Details
#initialize(workspace, graph) ⇒ TaskCache
Returns a new instance of TaskCache.
10 11 12 13 14 15 16 |
# File 'lib/rwm/task_cache.rb', line 10 def initialize(workspace, graph) @workspace = workspace @graph = graph @cache_dir = File.join(workspace.root, ".rwm", "cache") @content_hashes = {} @cache_declarations = {} end |
Instance Method Details
#cache_declarations(package) ⇒ Object
Discover cacheable task declarations by running ‘bundle exec rake rwm:cache_config`
78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/rwm/task_cache.rb', line 78 def cache_declarations(package) return @cache_declarations[package.name] if @cache_declarations.key?(package.name) output = `cd #{Shellwords.escape(package.path)} && bundle exec rake rwm:cache_config 2>/dev/null` @cache_declarations[package.name] = if $?.success? && !output.strip.empty? JSON.parse(output.strip) else {} end rescue JSON::ParserError @cache_declarations[package.name] = {} end |
#cacheable?(package, task) ⇒ Boolean
Returns true if the task is declared cacheable in the package’s Rakefile
19 20 21 22 |
# File 'lib/rwm/task_cache.rb', line 19 def cacheable?(package, task) declarations = cache_declarations(package) declarations.key?(task) end |
#cached?(package, task) ⇒ Boolean
Returns true if the (package, task) pair is cached and inputs haven’t changed. Also verifies declared outputs exist (if any).
26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/rwm/task_cache.rb', line 26 def cached?(package, task) stored = read_stored_hash(package, task) return false unless stored return false unless stored == content_hash(package) # If outputs are declared, they must exist decl = cache_declarations(package)[task] if decl && decl["output"] return false unless outputs_exist?(package, decl["output"]) end true end |
#content_hash(package) ⇒ Object
Compute a content hash for a package: SHA256 of all source files + dependency hashes
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/rwm/task_cache.rb', line 54 def content_hash(package) return @content_hashes[package.name] if @content_hashes.key?(package.name) digest = Digest::SHA256.new # Hash all source files in the package (sorted for determinism) source_files(package).each do |file| rel_path = file.delete_prefix("#{package.path}/") digest.update(rel_path) digest.update(File.read(file)) end # Include dependency content hashes (transitive invalidation) @graph.dependencies(package.name).sort.each do |dep_name| dep_pkg = @workspace.find_package(dep_name) digest.update(content_hash(dep_pkg)) rescue PackageNotFoundError next end @content_hashes[package.name] = digest.hexdigest end |
#outputs_exist?(package, output_pattern) ⇒ Boolean
Check if declared output files/globs exist in the package directory
48 49 50 51 |
# File 'lib/rwm/task_cache.rb', line 48 def outputs_exist?(package, output_pattern) matches = Dir.glob(File.join(package.path, output_pattern)) !matches.empty? end |
#store(package, task) ⇒ Object
Store the current content hash after a successful task run
41 42 43 44 45 |
# File 'lib/rwm/task_cache.rb', line 41 def store(package, task) FileUtils.mkdir_p(@cache_dir) path = cache_file(package, task) File.write(path, content_hash(package)) end |