cache

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 11, 2026 License: AGPL-3.0 Imports: 24 Imported by: 0

Documentation

Overview

Package cache provides ephemeral graph caching with LRU eviction.

The cache package implements an in-memory cache for code graphs with:

  • Reference counting for safe eviction
  • Copy-on-write incremental updates
  • Singleflight deduplication of concurrent builds
  • LRU eviction with configurable limits

Design Principles

Graphs are ephemeral and always rebuildable from source code files. The cache is a performance optimization, not a source of truth.

Thread Safety

GraphCache is safe for concurrent use. Individual CacheEntry structs are safe for concurrent reads but require the entry's mutex for writes.

Index

Constants

View Source
const (
	// DefaultMaxEntries is the default maximum number of cached graphs.
	DefaultMaxEntries = 5

	// DefaultMaxAge is the default TTL for cached entries.
	DefaultMaxAge = 30 * time.Minute

	// DefaultErrorCacheTTL is how long build errors are cached.
	DefaultErrorCacheTTL = 5 * time.Second

	// DefaultSourceHashTTL is how long the source hash is cached to avoid
	// recomputing on every request. Set to 5 seconds for fast change detection.
	DefaultSourceHashTTL = 5 * time.Second
)

Default configuration values.

View Source
const GraphBuilderVersion = "2026.02.08.gr42"

GR-42: Graph Builder Versioning

GraphBuilderVersion is incremented when graph structure changes. Cached graphs with different versions are automatically rebuilt.

Increment when:

  • New edge types added (e.g., EdgeTypeImplements in GR-40)
  • Parser changes affect symbol extraction
  • Graph builder logic changes

Format: YYYY.MM.DD.feature

Variables

View Source
var (
	// ErrCacheEntryInUse is returned when attempting to evict an entry
	// that has active references.
	ErrCacheEntryInUse = errors.New("cache entry in use")

	// ErrEntryNotFound is returned when the requested entry doesn't exist.
	ErrEntryNotFound = errors.New("cache entry not found")

	// ErrCacheStale is returned when an entry has been marked as stale.
	ErrCacheStale = errors.New("cache entry is stale")
)

Sentinel errors for cache operations.

View Source
var DefaultSkipDirectories = map[string]bool{
	".git":         true,
	"node_modules": true,
	"vendor":       true,
	".venv":        true,
	"__pycache__":  true,
	"target":       true,

	".idea":    true,
	".vscode":  true,
	"build":    true,
	"dist":     true,
	"bin":      true,
	".next":    true,
	"coverage": true,
	".cache":   true,
	"tmp":      true,
	".tox":     true,
	"eggs":     true,
	".eggs":    true,
}

DefaultSkipDirectories are directories skipped during hash computation. M2: Extended list of commonly generated/vendored directories.

View Source
var DefaultSourceExtensions = map[string]bool{
	".go":    true,
	".py":    true,
	".ts":    true,
	".tsx":   true,
	".js":    true,
	".jsx":   true,
	".java":  true,
	".kt":    true,
	".rs":    true,
	".c":     true,
	".cpp":   true,
	".h":     true,
	".hpp":   true,
	".rb":    true,
	".swift": true,
}

DefaultSourceExtensions are the file extensions checked for staleness. Can be overridden per-call using ComputeSourceHashWithExtensions.

Functions

func ClearHashCache

func ClearHashCache()

ClearHashCache clears the entire source hash cache. Useful for testing.

func ComputeSourceHash

func ComputeSourceHash(ctx context.Context, root string) (string, int, error)

ComputeSourceHash computes a hash of source file metadata.

Description:

Walks the project directory and computes a SHA256 hash of
(relative_path, mtime, size) for all source files. Files are
sorted alphabetically for deterministic hashing (H2 fix).

Inputs:

ctx - Context for cancellation. Must not be nil.
root - Absolute path to project root. Must exist.

Outputs:

string - Hex-encoded SHA256 hash (64 chars).
int - Number of files included in hash.
error - Non-nil if walk failed or was cancelled.

Example:

hash, count, err := ComputeSourceHash(ctx, "/path/to/project")
if err != nil {
    return fmt.Errorf("compute hash: %w", err)
}
fmt.Printf("Hash: %s (%d files)\n", hash[:16], count)

Thread Safety: Safe for concurrent use.

Complexity: O(N log N) where N = number of files (due to sorting).

Limitations:

  • Skips symlinks to avoid infinite loops
  • Returns error if >100K files (likely wrong directory)
  • Uses mtime which may not detect content-preserving copies

Assumptions:

  • ctx is not nil
  • root is a valid directory path
  • Filesystem mtime has sufficient granularity (may fail on some network filesystems)

func ComputeSourceHashWithExtensions

func ComputeSourceHashWithExtensions(ctx context.Context, root string, extensions map[string]bool) (string, int, error)

ComputeSourceHashWithExtensions computes hash with custom extensions. M1 fix.

If extensions is nil, uses DefaultSourceExtensions.

func GenerateGraphID

func GenerateGraphID(projectRoot string) string

GenerateGraphID creates a stable ID for a project root.

Uses full SHA256 (64 hex chars) to eliminate collision risk.

func HashCacheSize

func HashCacheSize() int

HashCacheSize returns the current number of entries in the hash cache. Useful for monitoring.

func InvalidateHashCache

func InvalidateHashCache(root string)

InvalidateHashCache clears the source hash cache for a project. Called when files are known to have changed.

func NewTestHashCache

func NewTestHashCache() *sourceHashCache

NewTestHashCache creates a hash cache for testing. C2 fix.

func SetHashCache

func SetHashCache(cache *sourceHashCache) func()

SetHashCache replaces the global hash cache (for testing). C2 fix. Returns a cleanup function that restores the original cache.

Types

type AnalyzeFunc

type AnalyzeFunc func(ctx context.Context, symbolID string) (*analysis.EnhancedBlastRadius, error)

AnalyzeFunc is the function signature for computing blast radius.

type BRCacheOption

type BRCacheOption func(*BRCacheOptions)

BRCacheOption is a functional option for configuring BlastRadiusCache.

func WithBRComputeTimeout

func WithBRComputeTimeout(d time.Duration) BRCacheOption

WithBRComputeTimeout sets the analysis timeout.

func WithBRMaxAge

func WithBRMaxAge(d time.Duration) BRCacheOption

WithBRMaxAge sets the TTL for cached entries.

func WithBRMaxEntries

func WithBRMaxEntries(n int) BRCacheOption

WithBRMaxEntries sets the maximum number of cached entries.

type BRCacheOptions

type BRCacheOptions struct {
	// MaxEntries is the maximum number of cached results.
	// Default: 1000
	MaxEntries int

	// MaxAge is the TTL for cached entries.
	// Default: 5 minutes
	MaxAge time.Duration

	// ComputeTimeout is the maximum time for a single analysis.
	// Default: 500ms
	ComputeTimeout time.Duration
}

BRCacheOptions configures BlastRadiusCache.

func DefaultBRCacheOptions

func DefaultBRCacheOptions() BRCacheOptions

DefaultBRCacheOptions returns sensible defaults.

type BRCacheStats

type BRCacheStats struct {
	EntryCount int
	Hits       int64
	Misses     int64
	Evictions  int64
	Computes   int64
	ErrorCount int64
	MaxEntries int
	MaxAge     time.Duration
}

BRCacheStats contains statistics about the cache.

func (BRCacheStats) HitRate

func (s BRCacheStats) HitRate() float64

HitRate returns the cache hit rate as a percentage.

type BlastRadiusCache

type BlastRadiusCache struct {
	// contains filtered or unexported fields
}

BlastRadiusCache provides LRU caching for blast radius analysis results.

Description

Caches EnhancedBlastRadius results to avoid redundant analysis. Uses graph generation as cache key to automatically invalidate when the graph changes.

Cache Key Format

Keys are computed as: SHA256(projectRoot + ":" + symbolID + ":" + graphGeneration) This ensures cache entries are invalidated when:

  • The target symbol changes
  • The graph is rebuilt

Thread Safety

Safe for concurrent use. Uses sync.RWMutex for entry map and singleflight.Group for analysis deduplication.

func NewBlastRadiusCache

func NewBlastRadiusCache(opts ...BRCacheOption) *BlastRadiusCache

NewBlastRadiusCache creates a new BlastRadiusCache.

func (*BlastRadiusCache) Clear

func (c *BlastRadiusCache) Clear()

Clear removes all entries from the cache.

func (*BlastRadiusCache) Get

func (c *BlastRadiusCache) Get(symbolID string, graphGen uint64) (*analysis.EnhancedBlastRadius, bool)

Get retrieves a cached blast radius result.

Inputs

  • symbolID: The target symbol identifier.
  • graphGen: The current graph generation.

Outputs

  • *analysis.EnhancedBlastRadius: The cached result, or nil if not found.
  • bool: True if the entry was found and valid.

func (*BlastRadiusCache) GetOrCompute

func (c *BlastRadiusCache) GetOrCompute(
	ctx context.Context,
	symbolID string,
	graphGen uint64,
	compute AnalyzeFunc,
) (*analysis.EnhancedBlastRadius, error)

GetOrCompute retrieves a cached result or computes a new one.

Description

Uses singleflight to deduplicate concurrent computations for the same symbol. If multiple goroutines request the same symbol simultaneously, only one computation runs and all waiters receive the result.

Inputs

  • ctx: Context for cancellation.
  • symbolID: The target symbol identifier.
  • graphGen: The current graph generation.
  • compute: Function to compute the blast radius if not cached.

Outputs

  • *analysis.EnhancedBlastRadius: The result (cached or newly computed).
  • error: Non-nil if computation failed.

func (*BlastRadiusCache) Invalidate

func (c *BlastRadiusCache) Invalidate(symbolID string, graphGen uint64)

Invalidate removes a specific entry.

func (*BlastRadiusCache) InvalidateAll

func (c *BlastRadiusCache) InvalidateAll(symbolID string)

InvalidateAll removes all entries for a symbol (any generation).

func (*BlastRadiusCache) InvalidateByGeneration

func (c *BlastRadiusCache) InvalidateByGeneration(graphGen uint64)

InvalidateByGeneration removes all entries for a specific graph generation.

func (*BlastRadiusCache) Len

func (c *BlastRadiusCache) Len() int

Len returns the number of entries in the cache.

func (*BlastRadiusCache) Stats

func (c *BlastRadiusCache) Stats() BRCacheStats

Stats returns current cache statistics.

type BuildFunc

type BuildFunc func(ctx context.Context, projectRoot string) (*graph.Graph, *manifest.Manifest, error)

BuildFunc is the function signature for building a graph.

type CacheEntry

type CacheEntry struct {
	// GraphID is the unique identifier for this cache entry.
	// Format: full SHA256 of project root (64 hex chars).
	GraphID string

	// ProjectRoot is the absolute path to the project.
	ProjectRoot string

	// Graph is the cached code graph.
	Graph *graph.Graph

	// Manifest contains the file hashes at build time.
	// Used for change detection.
	Manifest *manifest.Manifest

	// GR-42: BuilderVersion is the GraphBuilderVersion at build time.
	// If this doesn't match current GraphBuilderVersion, the cache is stale.
	BuilderVersion string

	// GR-42: SourceHash is a hash of source file metadata (path + mtime + size).
	// Used for fast staleness detection without reading file contents.
	SourceHash string

	// BuiltAtMilli is when the graph was built.
	BuiltAtMilli int64

	// LastAccessMilli is when the entry was last accessed.
	LastAccessMilli int64
	// contains filtered or unexported fields
}

CacheEntry represents a cached graph with its metadata.

Thread Safety:

CacheEntry is safe for concurrent reads. The mu mutex must be
held for write operations like Refresh.

func (*CacheEntry) Acquire

func (e *CacheEntry) Acquire()

Acquire increments the reference count.

Must be paired with a call to Release when done using the entry.

func (*CacheEntry) EstimatedMemoryBytes

func (e *CacheEntry) EstimatedMemoryBytes() int64

EstimatedMemoryBytes returns an approximate memory usage for this entry.

Description:

Estimates memory usage based on graph node/edge counts and manifest
file counts. Uses conservative estimates per element.

Inputs:

None. Reads from entry state.

Outputs:

int64 - Estimated memory usage in bytes.

Memory Estimation:

  • Per node: ~500 bytes (Node struct + Symbol pointer + slices)
  • Per edge: ~100 bytes (Edge struct + Location)
  • Per manifest file: ~200 bytes (FileEntry with path/hash)
  • Base overhead: ~1KB

Limitations:

Estimates are heuristic. Actual memory may differ due to:
- Go allocator overhead and alignment
- Varying string lengths in Symbol/FileEntry
- Runtime memory fragmentation

Assumptions:

Graph and Manifest are not nil, or method handles nil gracefully.

Thread Safety:

Safe for concurrent reads. Does not modify entry state.

func (*CacheEntry) InUse

func (e *CacheEntry) InUse() bool

InUse returns true if the entry has active references.

func (*CacheEntry) IsStale

func (e *CacheEntry) IsStale() bool

IsStale returns true if the entry has been marked as stale.

func (*CacheEntry) MarkStale

func (e *CacheEntry) MarkStale()

MarkStale marks the entry as stale using atomic operations.

func (*CacheEntry) RefCount

func (e *CacheEntry) RefCount() int32

RefCount returns the current reference count.

func (*CacheEntry) Release

func (e *CacheEntry) Release()

Release decrements the reference count.

type CacheOption

type CacheOption func(*CacheOptions)

CacheOption is a functional option for configuring GraphCache.

func WithErrorCacheTTL

func WithErrorCacheTTL(d time.Duration) CacheOption

WithErrorCacheTTL sets how long build errors are cached.

func WithMaxAge

func WithMaxAge(d time.Duration) CacheOption

WithMaxAge sets the TTL for cached entries.

func WithMaxEntries

func WithMaxEntries(n int) CacheOption

WithMaxEntries sets the maximum number of cached entries.

func WithMaxMemoryMB

func WithMaxMemoryMB(mb int) CacheOption

WithMaxMemoryMB sets the soft memory limit.

func WithStalenessCheck

func WithStalenessCheck(enabled bool) CacheOption

WithStalenessCheck enables or disables staleness checking. A2 Fix.

When disabled, cached entries are returned without checking if source files have changed. Use this in production environments where deployments are immutable and source files don't change during server lifetime.

Default: true (staleness checking enabled)

type CacheOptions

type CacheOptions struct {
	// MaxEntries is the maximum number of cached graphs.
	MaxEntries int

	// MaxAge is the TTL for cached entries.
	MaxAge time.Duration

	// MaxMemoryMB is the soft memory limit (0 = unlimited).
	MaxMemoryMB int

	// ErrorCacheTTL is how long build errors are cached.
	ErrorCacheTTL time.Duration

	// A2 Fix: DisableStalenessCheck skips staleness checking on cache hits.
	// Use in production environments with immutable deployments where
	// source files don't change during server lifetime.
	DisableStalenessCheck bool
}

CacheOptions configures GraphCache behavior.

func DefaultCacheOptions

func DefaultCacheOptions() CacheOptions

DefaultCacheOptions returns sensible defaults.

type CacheStats

type CacheStats struct {
	// EntryCount is the number of entries in the cache.
	EntryCount int

	// Hits is the number of cache hits.
	Hits int64

	// Misses is the number of cache misses.
	Misses int64

	// Evictions is the number of entries evicted.
	Evictions int64

	// MemoryEvictions is the number of entries evicted due to memory pressure.
	MemoryEvictions int64

	// BuildCount is the number of graphs built.
	BuildCount int64

	// RefreshCount is the number of incremental updates.
	RefreshCount int64

	// ErrorCount is the number of build errors.
	ErrorCount int64

	// GR-42: StaleRebuilds is the number of rebuilds triggered by staleness detection.
	StaleRebuilds int64

	// MaxEntries is the configured maximum entries.
	MaxEntries int

	// MaxAge is the configured TTL.
	MaxAge time.Duration

	// MaxMemoryMB is the configured memory limit (0 = unlimited).
	MaxMemoryMB int

	// EstimatedMemoryMB is the current estimated memory usage.
	EstimatedMemoryMB int
}

CacheStats contains statistics about the cache.

func (CacheStats) HitRate

func (s CacheStats) HitRate() float64

HitRate returns the cache hit rate as a percentage.

type ErrBuildFailed

type ErrBuildFailed struct {
	// Err is the underlying build error.
	Err error

	// FailedAt is when the build failed.
	FailedAt time.Time

	// RetryAt is when a retry is allowed.
	RetryAt time.Time
}

ErrBuildFailed wraps a build error with timing information.

When a build fails, the error is cached to prevent retry storms. This error type includes when the failure occurred and when a retry is allowed.

func (*ErrBuildFailed) CanRetry

func (e *ErrBuildFailed) CanRetry() bool

CanRetry returns true if the retry time has passed.

func (*ErrBuildFailed) Error

func (e *ErrBuildFailed) Error() string

Error implements the error interface.

func (*ErrBuildFailed) Unwrap

func (e *ErrBuildFailed) Unwrap() error

Unwrap returns the underlying error for errors.Is/As support.

type GraphCache

type GraphCache struct {
	// contains filtered or unexported fields
}

GraphCache provides LRU caching for code graphs with reference counting.

Thread Safety:

GraphCache is safe for concurrent use. Uses RWMutex for the entry map
and per-entry mutexes for refresh operations.

func NewGraphCache

func NewGraphCache(opts ...CacheOption) *GraphCache

NewGraphCache creates a new GraphCache with the given options.

func (*GraphCache) Clear

func (c *GraphCache) Clear()

Clear removes all entries from the cache.

Entries with active references are marked as stale.

func (*GraphCache) ForceInvalidate

func (c *GraphCache) ForceInvalidate(projectRoot string)

ForceInvalidate marks an entry as stale.

The entry will be removed when all references are released. Stale entries are not returned by Get().

func (*GraphCache) Get

func (c *GraphCache) Get(projectRoot string) (*CacheEntry, func(), bool)

Get retrieves a cached entry by project root.

Returns the entry, a release function, and whether the entry was found. The release function MUST be called when done using the entry.

If the entry is stale or expired, returns false.

func (*GraphCache) GetOrBuild

func (c *GraphCache) GetOrBuild(ctx context.Context, projectRoot string, build BuildFunc) (*CacheEntry, func(), error)

GetOrBuild retrieves a cached entry or builds a new one.

Description:

Retrieves a cached graph entry, checking for staleness before returning.
If the entry is stale (builder version mismatch or source files changed),
it is automatically invalidated and rebuilt.

Inputs:

ctx - Context for cancellation. Must not be nil.
projectRoot - Absolute path to the project root.
build - Function to build the graph if not cached or stale.

Outputs:

*CacheEntry - The cached or freshly built entry.
func() - Release function that MUST be called when done.
error - Non-nil if build failed.

Behavior:

Uses singleflight to deduplicate concurrent builds for the same project.
Build errors are cached for ErrorCacheTTL to prevent retry storms.
GR-42: Checks staleness on every cache hit to ensure fresh graphs.

Thread Safety: Safe for concurrent use.

func (*GraphCache) Invalidate

func (c *GraphCache) Invalidate(projectRoot string) error

Invalidate removes an entry from the cache.

Returns ErrCacheEntryInUse if the entry has active references. Use ForceInvalidate to mark the entry as stale instead.

func (*GraphCache) Refresh

func (c *GraphCache) Refresh(ctx context.Context, projectRoot string, refresh RefreshFunc) error

Refresh performs a copy-on-write incremental update of a cached entry.

Description:

Uses the provided RefreshFunc to detect and apply changes to the
cached graph. The update is performed atomically using copy-on-write:
concurrent readers see either the old or new state, never partial.

Inputs:

ctx - Context for cancellation.
projectRoot - Absolute path to the project root.
refresh - Function that performs the incremental update.

Outputs:

error - Non-nil if the entry doesn't exist or refresh failed.

Errors:

ErrEntryNotFound - No cached entry for this project
Other errors from the RefreshFunc

Behavior:

  1. Acquires the entry and its refresh mutex
  2. Calls RefreshFunc with current graph/manifest
  3. If no changes, returns immediately
  4. Creates new entry with updated graph/manifest
  5. Atomically swaps the entry in the cache
  6. Marks old entry as stale

Thread Safety:

Safe for concurrent use. Concurrent readers see consistent state.
Only one Refresh can run at a time per entry (protected by entry mutex).

func (*GraphCache) Stats

func (c *GraphCache) Stats() CacheStats

Stats returns current cache statistics.

type HotPathPrecomputer

type HotPathPrecomputer struct {
	// contains filtered or unexported fields
}

HotPathPrecomputer pre-computes blast radius for frequently accessed symbols.

Description

Tracks which symbols are accessed most frequently and pre-computes their blast radius results in the background. This warms the cache for hot paths so user requests can be served from cache immediately.

Algorithm

Uses a min-heap to track the top N most accessed symbols. When a symbol is accessed, its count is incremented. Periodically, the precomputer runs the top symbols through the analysis and caches the results.

Thread Safety

Safe for concurrent use. Access recording is non-blocking via atomic counters.

func NewHotPathPrecomputer

func NewHotPathPrecomputer(
	cache *BlastRadiusCache,
	computeFunc AnalyzeFunc,
	graphGenFunc func() uint64,
	opts *PrecomputerOptions,
) *HotPathPrecomputer

NewHotPathPrecomputer creates a new precomputer.

Inputs

  • cache: The blast radius cache to warm.
  • computeFunc: Function to compute blast radius (passed to cache.GetOrCompute).
  • graphGenFunc: Function returning the current graph generation.
  • opts: Optional configuration (nil uses defaults).

Outputs

  • *HotPathPrecomputer: Ready-to-use precomputer (call Start to begin).

func (*HotPathPrecomputer) Clear

func (p *HotPathPrecomputer) Clear()

Clear resets all access tracking.

func (*HotPathPrecomputer) GetTopSymbols

func (p *HotPathPrecomputer) GetTopSymbols(n int) []string

GetTopSymbols returns the top N most accessed symbols.

func (*HotPathPrecomputer) IsRunning

func (p *HotPathPrecomputer) IsRunning() bool

IsRunning returns true if the precomputer is active.

func (*HotPathPrecomputer) RecordAccess

func (p *HotPathPrecomputer) RecordAccess(symbolID string)

RecordAccess records an access to a symbol.

Description

Called when a symbol's blast radius is requested. The access count is incremented atomically for thread-safe recording without locks.

Inputs

  • symbolID: The accessed symbol identifier.

func (*HotPathPrecomputer) Start

func (p *HotPathPrecomputer) Start(ctx context.Context)

Start begins the background pre-computation loop.

Inputs

  • ctx: Context for cancellation.

func (*HotPathPrecomputer) Stats

Stats returns current statistics.

func (*HotPathPrecomputer) Stop

func (p *HotPathPrecomputer) Stop()

Stop stops the precomputer.

type PrecomputerOptions

type PrecomputerOptions struct {
	// MaxTracked is the maximum number of symbols to track access for.
	// Default: 10000
	MaxTracked int

	// TopN is how many top symbols to pre-compute.
	// Default: 100
	TopN int

	// Interval is how often to run pre-computation.
	// Default: 1 minute
	Interval time.Duration
}

PrecomputerOptions configures the HotPathPrecomputer.

func DefaultPrecomputerOptions

func DefaultPrecomputerOptions() PrecomputerOptions

DefaultPrecomputerOptions returns sensible defaults.

type PrecomputerStats

type PrecomputerStats struct {
	TrackedSymbols int
	HotSymbols     int64
	TotalAccess    int64
	Precomputes    int64
	LastRunMilli   int64
	IsRunning      bool
}

PrecomputerStats contains statistics about the precomputer.

type RefreshFunc

type RefreshFunc func(ctx context.Context, projectRoot string, currentGraph *graph.Graph, currentManifest *manifest.Manifest) (*graph.Graph, *manifest.Manifest, error)

RefreshFunc is the function signature for incrementally updating a graph.

Description:

Called during Refresh to handle the incremental update logic.
The function receives the current graph/manifest and should return
updated versions based on file system changes.

Inputs:

ctx - Context for cancellation.
projectRoot - Absolute path to the project root.
currentGraph - The current graph (will be cloned by caller).
currentManifest - The current manifest for change detection.

Outputs:

*graph.Graph - The updated graph (may be same if no changes).
*manifest.Manifest - The new manifest reflecting current state.
error - Non-nil if refresh failed.

Behavior:

The RefreshFunc should:
1. Scan for file changes (added/modified/deleted)
2. Clone the graph if changes exist
3. Remove deleted files from clone
4. Re-parse and merge modified/added files
5. Return the updated graph and new manifest

type StalenessReason

type StalenessReason string

StalenessReason indicates why a cache entry is stale.

const (
	// StalenessNone indicates the cache is valid.
	StalenessNone StalenessReason = ""

	// StalenessVersionMismatch indicates the builder version changed.
	StalenessVersionMismatch StalenessReason = "builder_version_mismatch"

	// StalenessSourceChanged indicates source files changed.
	StalenessSourceChanged StalenessReason = "source_files_changed"

	// StalenessHashError indicates an error computing source hash.
	StalenessHashError StalenessReason = "hash_computation_error"
)

func CheckStaleness

func CheckStaleness(ctx context.Context, entry *CacheEntry) (StalenessReason, error)

CheckStaleness determines if a cache entry is stale.

Description:

Checks if the cached graph is stale by comparing:
1. Builder version (must match current GraphBuilderVersion)
2. Source hash (must match current source files)

Inputs:

ctx - Context for cancellation. Must not be nil.
entry - The cache entry to check. Must not be nil.

Outputs:

StalenessReason - The reason for staleness, or StalenessNone if valid.
error - Non-nil only if hash computation failed. Note: when error is non-nil,
        reason is always StalenessHashError.

Example:

reason, err := CheckStaleness(ctx, entry)
if err != nil {
    // Hash computation failed - treat as stale but log error
    slog.Warn("staleness check failed", slog.String("error", err.Error()))
}
if reason != StalenessNone {
    // Entry is stale, needs rebuild
}

Thread Safety: Safe for concurrent use.

Assumptions:

  • ctx is not nil
  • entry is not nil and has valid ProjectRoot

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL