cache

package
v1.6.2 Latest Latest
Warning

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

Go to latest
Published: May 13, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package cache provides a minimal caching interface for the pipeline.

The cache abstraction allows different storage backends:

  • File-based (CLI)
  • In-memory (testing)
  • Redis (cloud platform - implemented in stacktower-cloud)

The cache is used to store:

  • HTTP responses from package registries
  • Parsed dependency graphs
  • Computed layouts
  • Rendered artifacts

Cache keys are opaque strings generated by implementations. The pipeline doesn't need to know about key structure, scoping, or TTLs.

Index

Constants

View Source
const (
	TTLGraph        = 7 * 24 * time.Hour  // 1 week - dependency graphs change with new versions
	TTLLayout       = 30 * 24 * time.Hour // 30 days - layouts are stable once computed
	TTLArtifact     = 90 * 24 * time.Hour // 90 days - rendered artifacts rarely need regeneration
	TTLHTTPResponse = 24 * time.Hour      // 1 day - registry API responses (used by integrations)
)

Cache TTL constants for different artifact types. These define how long cached items remain valid before expiring.

Variables

View Source
var (
	// ErrNotFound is returned when a requested item does not exist.
	ErrNotFound = errors.New("not found")

	// ErrNetwork is returned for HTTP failures (timeouts, connection errors, 5xx responses).
	ErrNetwork = errors.New("network error")

	// ErrUnauthorized is returned when authentication fails (HTTP 401/403).
	// This typically means the API token is invalid, expired, or revoked.
	ErrUnauthorized = errors.New("unauthorized")

	// ErrCacheMiss is returned when an item is not found in cache.
	ErrCacheMiss = errors.New("cache miss")
)

Sentinel errors for caching operations.

Functions

func Hash

func Hash(data []byte) string

Hash computes a SHA-256 hash of the input data. Returns the full 64-character hex string.

func IsRetryable

func IsRetryable(err error) bool

IsRetryable checks if an error is wrapped with RetryableError.

func RetryWithBackoff

func RetryWithBackoff(ctx context.Context, fn func() error) error

RetryWithBackoff retries fn up to 3 times with exponential backoff. Only errors wrapped with Retryable will trigger retries.

func RetryWithBackoffRegistry

func RetryWithBackoffRegistry(ctx context.Context, registry string, fn func() error) error

RetryWithBackoffRegistry retries fn up to 3 times with exponential backoff, emitting observability hooks with the registry name for each retry.

func Retryable

func Retryable(err error) error

Retryable wraps an error as a RetryableError.

Types

type ArtifactKeyOpts

type ArtifactKeyOpts struct {
	Format       string `json:"format"`
	Style        string `json:"style,omitempty"`
	ShowEdges    bool   `json:"show_edges,omitempty"`
	Popups       bool   `json:"popups,omitempty"`
	Nebraska     bool   `json:"nebraska,omitempty"`
	Merge        bool   `json:"merge,omitempty"`
	Normalize    bool   `json:"normalize,omitempty"`
	ShowVulns    bool   `json:"show_vulns,omitempty"`
	ShowLicenses bool   `json:"show_licenses,omitempty"`
	FlagsOnTop   bool   `json:"flags_on_top,omitempty"`
}

ArtifactKeyOpts defines parameters that affect artifact rendering. Different options produce different artifacts, so they're part of the cache key.

IMPORTANT: This must include ALL options that affect rendering output:

  • Format: Output format (svg/png/pdf)
  • Style: Visual style (simple/handdrawn) - affects SVG structure
  • ShowEdges: Show dependency edges - adds <line> elements
  • Popups: Hover popups - adds metadata to SVG
  • Nebraska: Maintainer ranking - adds panel to visualization
  • Merge: Edge filtering for subdividers - affects which edges render
  • Normalize: Whether graph was normalized - changes node/edge count
  • ShowVulns: Whether vulnerability colours are rendered

When adding new render-time options to pipeline.Options, update this struct!

type Cache

type Cache interface {
	// Get retrieves a value by key.
	// Returns (data, true, nil) on hit.
	// Returns (nil, false, nil) on miss or expiration.
	// Returns (nil, false, err) on error.
	Get(ctx context.Context, key string) ([]byte, bool, error)

	// Set stores a value with the given TTL.
	// A TTL of 0 means no expiration.
	Set(ctx context.Context, key string, data []byte, ttl time.Duration) error

	// Delete removes a value from the cache.
	// Not finding the key is not an error.
	Delete(ctx context.Context, key string) error

	// Close releases any resources held by the cache.
	Close() error
}

Cache provides generic key-value caching with TTL support. All methods must be safe for concurrent use.

func NewFileCache

func NewFileCache(dir string) (Cache, error)

NewFileCache creates a file-based cache in the given directory. The directory will be created if it doesn't exist.

func NewInstrumentedCache

func NewInstrumentedCache(inner Cache) Cache

NewInstrumentedCache wraps a cache to emit CacheHooks on every operation.

func NewNullCache

func NewNullCache() Cache

NewNullCache creates a null cache.

type DefaultKeyer

type DefaultKeyer struct{}

DefaultKeyer provides a simple hash-based key generation strategy.

func (*DefaultKeyer) ArtifactKey

func (k *DefaultKeyer) ArtifactKey(layoutHash string, opts ArtifactKeyOpts) string

ArtifactKey generates a key for artifact caching.

func (*DefaultKeyer) GraphKey

func (k *DefaultKeyer) GraphKey(language, pkg string, opts GraphKeyOpts) string

GraphKey generates a key for dependency graph caching.

func (*DefaultKeyer) HTTPKey

func (k *DefaultKeyer) HTTPKey(namespace, key string) string

HTTPKey generates a key for HTTP response caching.

func (*DefaultKeyer) LayoutKey

func (k *DefaultKeyer) LayoutKey(graphHash string, opts LayoutKeyOpts) string

LayoutKey generates a key for layout caching.

type FileCache

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

FileCache implements a file-based cache for CLI usage. Cache entries are stored as files in a directory with metadata (expiration).

func (*FileCache) Close

func (c *FileCache) Close() error

Close does nothing for file cache.

func (*FileCache) Delete

func (c *FileCache) Delete(ctx context.Context, key string) error

Delete removes a value from the cache.

func (*FileCache) Get

func (c *FileCache) Get(ctx context.Context, key string) ([]byte, bool, error)

Get retrieves a value from the cache.

func (*FileCache) Set

func (c *FileCache) Set(ctx context.Context, key string, data []byte, ttl time.Duration) error

Set stores a value in the cache.

type GraphKeyOpts

type GraphKeyOpts struct {
	MaxDepth          int    `json:"max_depth"`
	MaxNodes          int    `json:"max_nodes"`
	Enriched          bool   `json:"enriched,omitempty"`           // Whether GitHub metadata enrichment was performed
	SecurityScan      bool   `json:"security_scan,omitempty"`      // Whether vulnerability scan data is included
	IncludePrerelease bool   `json:"include_prerelease,omitempty"` // Whether prerelease versions were included
	DependencyScope   string `json:"dependency_scope,omitempty"`   // Whether graph includes prod-only or all dependency groups
	RuntimeVersion    string `json:"runtime_version,omitempty"`    // Target runtime version for marker evaluation (e.g., "3.11" for Python)
}

GraphKeyOpts defines parameters that affect graph resolution during parsing. Different options produce different graphs, so they're part of the cache key. Note: Normalization is applied during layout, not parsing, so it's not here.

type InstrumentedCache

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

InstrumentedCache wraps a Cache and emits observability hooks on Get/Set operations.

func (*InstrumentedCache) Close

func (c *InstrumentedCache) Close() error

func (*InstrumentedCache) Delete

func (c *InstrumentedCache) Delete(ctx context.Context, key string) error

func (*InstrumentedCache) Dir

func (c *InstrumentedCache) Dir() string

Dir returns the underlying directory for FileCache, empty string otherwise.

func (*InstrumentedCache) Get

func (c *InstrumentedCache) Get(ctx context.Context, key string) ([]byte, bool, error)

func (*InstrumentedCache) Set

func (c *InstrumentedCache) Set(ctx context.Context, key string, data []byte, ttl time.Duration) error

type Keyer

type Keyer interface {
	// HTTPKey generates a key for HTTP response caching.
	// namespace isolates different registries (e.g., "npm:", "pypi:").
	HTTPKey(namespace, key string) string

	// GraphKey generates a key for dependency graph caching.
	GraphKey(language, pkg string, opts GraphKeyOpts) string

	// LayoutKey generates a key for layout caching.
	LayoutKey(graphHash string, opts LayoutKeyOpts) string

	// ArtifactKey generates a key for artifact caching.
	ArtifactKey(layoutHash string, opts ArtifactKeyOpts) string
}

Keyer generates cache keys for pipeline artifacts. Implementations should produce stable, collision-resistant keys.

func NewDefaultKeyer

func NewDefaultKeyer() Keyer

NewDefaultKeyer creates a default keyer.

func NewScopedKeyer

func NewScopedKeyer(inner Keyer, prefix string) Keyer

NewScopedKeyer creates a keyer with a prefix. The prefix is prepended to all generated keys.

type LayoutKeyOpts

type LayoutKeyOpts struct {
	VizType   string  `json:"viz_type"`
	Width     float64 `json:"width"`
	Height    float64 `json:"height"`
	Normalize bool    `json:"normalize,omitempty"` // Whether normalization was applied
	Ordering  string  `json:"ordering,omitempty"`
	Merge     bool    `json:"merge,omitempty"`
	Randomize bool    `json:"randomize,omitempty"`
	Seed      uint64  `json:"seed,omitempty"`
}

LayoutKeyOpts defines parameters that affect layout computation. Different options produce different layouts, so they're part of the cache key.

type NullCache

type NullCache struct{}

NullCache is a no-op cache that never stores anything. Useful for testing or when caching should be disabled.

func (*NullCache) Close

func (c *NullCache) Close() error

Close does nothing.

func (*NullCache) Delete

func (c *NullCache) Delete(ctx context.Context, key string) error

Delete does nothing.

func (*NullCache) Get

func (c *NullCache) Get(ctx context.Context, key string) ([]byte, bool, error)

Get always returns a cache miss.

func (*NullCache) Set

func (c *NullCache) Set(ctx context.Context, key string, data []byte, ttl time.Duration) error

Set does nothing.

type RetryableError

type RetryableError struct{ Err error }

RetryableError wraps an error to indicate it should trigger a retry.

func (*RetryableError) Error

func (e *RetryableError) Error() string

Error returns the error message of the wrapped error.

func (*RetryableError) Unwrap

func (e *RetryableError) Unwrap() error

Unwrap returns the wrapped error.

type ScopedKeyer

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

ScopedKeyer wraps a Keyer with a prefix for multi-tenant isolation. This is useful in the cloud platform where different users or contexts need separate cache namespaces.

Example usage:

// User-specific keys for private repos
userKeyer := NewScopedKeyer(NewDefaultKeyer(), "user:abc123:")

// Global keys for public packages
globalKeyer := NewDefaultKeyer()

func (*ScopedKeyer) ArtifactKey

func (k *ScopedKeyer) ArtifactKey(layoutHash string, opts ArtifactKeyOpts) string

ArtifactKey generates a prefixed key for artifact caching.

func (*ScopedKeyer) GraphKey

func (k *ScopedKeyer) GraphKey(language, pkg string, opts GraphKeyOpts) string

GraphKey generates a prefixed key for dependency graph caching.

func (*ScopedKeyer) HTTPKey

func (k *ScopedKeyer) HTTPKey(namespace, key string) string

HTTPKey generates a prefixed key for HTTP response caching.

func (*ScopedKeyer) LayoutKey

func (k *ScopedKeyer) LayoutKey(graphHash string, opts LayoutKeyOpts) string

LayoutKey generates a prefixed key for layout caching.

Jump to

Keyboard shortcuts

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