Module: RSpecTracer::Tracker::FileDigest Private

Defined in:
lib/rspec_tracer/tracker/file_digest.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Process-wide SHA256 file-digest cache. Keyed on absolute path with [mtime_ns, size] as the freshness check — when the file's stat timestamps + size match the cached values, the prior digest is reused; otherwise the digest is recomputed and the cache entry refreshed.

The cache is populated lazily and never evicted within a process. Tracer runs are bounded (one rspec invocation per process), so unbounded growth is bounded by the project's dependency-graph size (typically << 10k unique files).

SystemCallError on stat / digest is treated as "file gone / unreadable" and returns nil — same graceful-degradation contract every call site already implemented locally before this module centralized them.

Thread-safety: rspec example execution is single-threaded (cold-subprocess contract); the cache uses a plain Hash without locking. Multi-threaded callers are unsupported (consistent with the rest of the tracer's threading model).

Class Method Summary collapse

Class Method Details

.compute(path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the SHA256 hex digest of path, or nil when the file can't be stat'd (missing / permission denied / racey delete). Subsequent calls for the same path with unchanged stat skip the digest computation entirely.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/rspec_tracer/tracker/file_digest.rb', line 35

def compute(path)
  stat = File.stat(path)
  key = (stat.mtime.to_i * 1_000_000_000) + stat.mtime.nsec
  size = stat.size
  cache = (@cache ||= {})
  cached = cache[path]
  return cached[2] if cached && cached[0] == key && cached[1] == size

  digest = Digest::SHA256.file(path).hexdigest
  cache[path] = [key, size, digest]
  digest
rescue SystemCallError
  nil
end

.reset!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Drop the cache. Tests that mutate file content in-place at nanosecond granularity (and so might collide on the mtime+size key) should call this between scenarios. Normal tracer runs never need it — the cache lives for one rspec invocation only.



55
56
57
# File 'lib/rspec_tracer/tracker/file_digest.rb', line 55

def reset!
  @cache = {}
end