cache

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package cache contains the experimental validation contracts used to measure directory-cache identity before the production store is selected.

Index

Constants

View Source
const (
	CurrentSchemaVersion uint32 = 1
	MaxManifestBytes     int64  = 256 << 20
	MaxManifestEntries   uint32 = 1_000_000
	MaxManifestMethods   uint32 = 64
	MaxManifestString    uint32 = 4096
	MaxManifestRoot      uint32 = 4096
)

Variables

View Source
var (
	ErrCacheAbsent       = errors.New("cache state absent")
	ErrCacheCorrupt      = errors.New("cache state corrupt")
	ErrCacheIncompatible = errors.New("cache state incompatible")
	ErrCachePermission   = errors.New("cache permission failure")
	ErrCacheLock         = errors.New("cache lock failure")
	ErrCachePersistence  = errors.New("cache persistence failure")
	ErrPruneNotApproved  = errors.New("cache prune requires a successful full walk")
)
View Source
var (
	ErrInvalidRoot         = errors.New("invalid canonical root")
	ErrSnapshotNotFound    = errors.New("cache snapshot not found")
	ErrGenerationConflict  = errors.New("cache generation conflict")
	ErrInvalidSnapshot     = errors.New("invalid cache snapshot")
	ErrCacheUnavailable    = errors.New("cache unavailable")
	ErrInvalidationRequest = errors.New("invalid invalidation request")
	ErrAggregateOverflow   = errors.New("aggregate exceeds numeric limits")
	ErrInvalidAggregate    = errors.New("invalid aggregate input")
	ErrLocationCollision   = errors.New("cache location root mismatch")
	ErrLockUnsupported     = errors.New("cache writer lock unsupported on this platform")
)

Stable error categories let the count path distinguish a cold cache from a generation conflict or invalid caller input without depending on storage.

Functions

func CanonicalRoot

func CanonicalRoot(root string) (string, error)

CanonicalRoot returns the stable root spelling shared by count, status, and clear. Existing symlinks are evaluated; a not-yet-existing path still gets a clean absolute spelling so management commands resolve the same hash.

func EncodeManifest

func EncodeManifest(manifest Manifest) ([]byte, error)

EncodeManifest serializes a deterministic, bounded binary manifest.

func WriteManifestAtomic

func WriteManifestAtomic(ctx context.Context, path string, manifest Manifest) error

WriteManifestAtomic publishes a complete manifest through a same-directory temporary file, sync, close, and rename sequence.

func WriteManifestForRoot

func WriteManifestForRoot(ctx context.Context, location CacheLocation, manifest Manifest) error

WriteManifestForRoot refuses to publish a snapshot under a different root.

Types

type AggregateResult

type AggregateResult struct {
	FileCount  int
	FileSize   int64
	Characters int
	Words      int
	Lines      int
	Methods    map[ContractKey]int
}

AggregateResult contains only values reducible across file boundaries. Identity fields intentionally stay per-file so directory membership and validation cannot be bypassed by a stored total.

func AggregateFileResults

func AggregateFileResults(results []FileResult) (AggregateResult, error)

AggregateFileResults proves that fresh and reusable per-file values use the same summation semantics. It performs no membership or cache validation.

type CacheError

type CacheError struct {
	Category  CacheFailureKind
	Operation string
	Path      string
	Err       error
}

CacheError preserves the underlying error while exposing a stable diagnostic category to callers and future CLI reporting.

func (*CacheError) Error

func (err *CacheError) Error() string

func (*CacheError) Is

func (err *CacheError) Is(target error) bool

func (*CacheError) Unwrap

func (err *CacheError) Unwrap() error

type CacheFailureKind

type CacheFailureKind string

CacheFailureKind is the diagnostic class for a cache operation. None of these failures should replace a correctly computed count with an error.

const (
	FailureNone         CacheFailureKind = ""
	FailureAbsent       CacheFailureKind = "absent"
	FailureCorrupt      CacheFailureKind = "corrupt"
	FailureIncompatible CacheFailureKind = "incompatible"
	FailurePermission   CacheFailureKind = "permission"
	FailureLock         CacheFailureKind = "lock"
	FailurePersistence  CacheFailureKind = "persistence"
)

func CacheFailureOf

func CacheFailureOf(err error) CacheFailureKind

CacheFailureOf extracts a stable diagnostic class without requiring callers to depend on the concrete persistence error type.

type CacheLocation

type CacheLocation struct {
	Root         string
	RootHash     string
	Directory    string
	ManifestPath string
}

CacheLocation is the complete resolved location for one canonical root.

func (CacheLocation) Ensure

func (location CacheLocation) Ensure(ctx context.Context) error

Ensure creates the root cache directory with user-only permissions. It is intentionally separate from Resolve so discovery remains side-effect free.

type ContractKey

type ContractKey struct {
	Method              string
	Encoding            string
	Implementation      string
	VocabularyDigest    string
	NormalizationPolicy string
	SpecialTokenPolicy  string
}

ContractKey identifies the exact tokenizer contract represented by a method value. Model aliases intentionally do not appear here when they resolve to the same tokenizer contract.

type DecisionKind

type DecisionKind string

DecisionKind describes how one current path should be scheduled.

const (
	DecisionHit        DecisionKind = "hit"
	DecisionPartialHit DecisionKind = "partial_hit"
	DecisionMiss       DecisionKind = "miss"
	DecisionStale      DecisionKind = "stale"
)

type Entry

type Entry struct {
	Observation FileObservation
	Digest      [sha256.Size]byte
}

Entry is the minimal per-file value needed by the validation prototype.

func CaptureEntry

func CaptureEntry(ctx context.Context, root, path string) (Entry, error)

CaptureEntry reads a file once and records its current observation and digest.

type FileClassification

type FileClassification uint8

FileClassification records the classification associated with the stored bytes.

const (
	ClassificationText FileClassification = iota + 1
	ClassificationBinary
)

type FileDecision

type FileDecision struct {
	Path            string
	Kind            DecisionKind
	Reason          InvalidationReason
	ReusableMethods []ContractKey
	MissingMethods  []ContractKey
}

FileDecision is the complete per-path scheduling decision. ReusableMethods are safe to aggregate; MissingMethods must be counted before aggregation. Stale decisions never represent current membership and must not aggregate.

type FileEntry

type FileEntry = FileResult

These aliases keep the Sequence 01 manifest prototype source-compatible while the domain names above become the persistence-independent contract.

type FileIdentity

type FileIdentity struct {
	RelativePath   string
	Size           int64
	ModTimeNS      int64
	ContentDigest  [32]byte
	Classification FileClassification
}

FileIdentity is the observed identity that must still match before a stored file result can be reused. RelativePath is slash-normalized and relative to the canonical root; callers own canonical-root normalization.

type FileObservation

type FileObservation struct {
	RelativePath string
	Size         int64
	ModTimeNS    int64
}

FileObservation is the filesystem identity stored with a cache entry.

type FileResult

type FileResult struct {
	Size           int64
	ModTimeNS      int64
	ContentDigest  [32]byte
	Classification FileClassification
	Characters     int
	Words          int
	Lines          int
	Methods        map[ContractKey]int
}

FileResult contains the reducible per-file values. Characters, words, and lines support approximation methods without rereading the file; Methods can contain only the contracts computed by one run so later updates can be merged without discarding reusable method values.

func (FileResult) Identity

func (result FileResult) Identity(path string) FileIdentity

Identity returns the identity represented by a stored result at path.

type FileStore

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

FileStore persists one complete snapshot per canonical root. A caller may compute updates from an optimistic load; Commit then reloads under the writer lock and only merges updates whose observed identity is compatible with the latest generation.

func NewDefaultFileStore

func NewDefaultFileStore() (*FileStore, error)

NewDefaultFileStore creates a filesystem-backed Store in the platform user cache directory.

func NewFileStore

func NewFileStore(resolver LocationResolver) *FileStore

NewFileStore creates a filesystem-backed Store using resolver's injected user-cache parent.

func (*FileStore) Clear

func (store *FileStore) Clear(ctx context.Context, root string) (err error)

Clear removes the current manifest under the same writer lock used by Commit. The lock file is retained as an inert coordination inode so a concurrent process cannot race directory removal with lock acquisition.

func (*FileStore) ClearAll

func (store *FileStore) ClearAll(ctx context.Context) (err error)

ClearAll removes every root cache while holding the global lifecycle lock. Root writers acquire that lock first, so a clear cannot race a commit.

func (*FileStore) Commit

func (store *FileStore) Commit(ctx context.Context, root string, baseGeneration uint64, updates UpdateSet) (err error)

Commit publishes one generation after reloading the latest state under an inter-process writer lock. Updates based on an older generation survive when they add a new path or preserve the latest path identity; a stale same-path identity is rejected instead of overwriting newer data.

func (*FileStore) CommitAndPrune

func (store *FileStore) CommitAndPrune(ctx context.Context, root string, baseGeneration uint64, updates UpdateSet, options PruneOptions) (err error)

CommitAndPrune publishes updates and removes entries absent from a successful full walk while holding one writer lock. If another writer has advanced the generation since the caller's load, the updates may still be merged, but pruning is skipped because the observed membership is no longer authoritative for the latest generation.

func (*FileStore) Load

func (store *FileStore) Load(ctx context.Context, root string) (*Snapshot, error)

Load returns the latest complete snapshot for root.

func (*FileStore) Prune

func (store *FileStore) Prune(ctx context.Context, root string, options PruneOptions) (pruned int, err error)

Prune removes entries absent from an explicitly successful full walk. A failed or narrow run returns ErrPruneNotApproved without changing state.

func (*FileStore) Status

func (store *FileStore) Status(ctx context.Context, root string) (Status, error)

Status reports whether a complete snapshot is present without creating a cache directory for a root that has never been committed.

type InvalidationPlan

type InvalidationPlan struct {
	Decisions []FileDecision
}

InvalidationPlan is deterministic by path and contains one decision for every current path plus stale entries from a compatible prior snapshot.

func PlanInvalidation

func PlanInvalidation(request InvalidationRequest, current map[string]FileIdentity, snapshot *Snapshot) (InvalidationPlan, error)

PlanInvalidation compares the authoritative current membership and observations with a cached snapshot. A nil snapshot is a cold cache. The function performs no I/O and never allows a stale entry to become current.

type InvalidationReason

type InvalidationReason string

InvalidationReason is a structured metric/diagnostic reason, not user-facing prose. New reasons should be added when a new invalidation input is added.

const (
	ReasonEntryMissing          InvalidationReason = "entry_missing"
	ReasonSchemaMismatch        InvalidationReason = "schema_mismatch"
	ReasonRootMismatch          InvalidationReason = "root_mismatch"
	ReasonPathChanged           InvalidationReason = "path_changed"
	ReasonSizeChanged           InvalidationReason = "size_changed"
	ReasonModTimeChanged        InvalidationReason = "modtime_changed"
	ReasonContentChanged        InvalidationReason = "content_changed"
	ReasonClassificationChanged InvalidationReason = "classification_changed"
	ReasonContractMissing       InvalidationReason = "contract_missing"
	ReasonIdentityMatch         InvalidationReason = "identity_match"
	ReasonMetadataAssumed       InvalidationReason = "metadata_assumed"
	ReasonVerifiedMatch         InvalidationReason = "verified_match"
	ReasonStaleEntry            InvalidationReason = "stale_entry"
)

type InvalidationRequest

type InvalidationRequest struct {
	Root          string
	SchemaVersion uint32
	Mode          ValidationMode
	Contracts     []ContractKey
}

InvalidationRequest contains the current cache compatibility inputs. Root membership is supplied separately because the current walk is authoritative.

type LocationResolver

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

LocationResolver maps every canonical root to one user-cache namespace. baseDir is the parent of the tcount namespace and is injectable for tests.

func NewLocationResolver

func NewLocationResolver() (LocationResolver, error)

NewLocationResolver uses os.UserCacheDir as the default parent. It does not create directories or modify the counted repository.

func NewLocationResolverAt

func NewLocationResolverAt(baseDir string) (LocationResolver, error)

NewLocationResolverAt injects a parent cache directory for tests and constrained deployments. The returned resolver still appends tcount/v1.

func (LocationResolver) Resolve

func (resolver LocationResolver) Resolve(root string) (CacheLocation, error)

Resolve returns the user-cache location for root without creating it.

type Manifest

type Manifest = Snapshot

func DecodeManifest

func DecodeManifest(data []byte) (Manifest, error)

DecodeManifest validates and decodes a bounded binary manifest.

func LoadManifest

func LoadManifest(ctx context.Context, path string) (Manifest, error)

LoadManifest reads a bounded manifest from disk.

func LoadManifestForRoot

func LoadManifestForRoot(ctx context.Context, location CacheLocation) (Manifest, error)

LoadManifestForRoot validates the stored canonical root after decoding. A hash collision or manually moved manifest therefore becomes a cold-safe location error instead of a reusable snapshot from another repository.

func MergeEntries

func MergeEntries(base Manifest, updates UpdateSet) (Manifest, error)

MergeEntries creates a new generation without mutating the base snapshot.

type MemoryStore

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

MemoryStore is a deterministic, persistence-independent Store for unit and integration development. It clones snapshots at both boundaries so callers cannot mutate a stored generation through a returned map.

func NewMemoryStore

func NewMemoryStore() *MemoryStore

NewMemoryStore creates an empty in-memory cache store.

func (*MemoryStore) Clear

func (store *MemoryStore) Clear(ctx context.Context, root string) error

Clear removes a root snapshot. Clearing an absent root is intentionally idempotent for management commands.

func (*MemoryStore) Commit

func (store *MemoryStore) Commit(ctx context.Context, root string, baseGeneration uint64, updates UpdateSet) error

Commit merges a complete or partial update set against the expected generation and publishes one new complete in-memory snapshot.

func (*MemoryStore) CommitAndPrune

func (store *MemoryStore) CommitAndPrune(ctx context.Context, root string, baseGeneration uint64, updates UpdateSet, options PruneOptions) error

CommitAndPrune applies updates and live-membership pruning atomically under the in-memory store lock.

func (*MemoryStore) Load

func (store *MemoryStore) Load(ctx context.Context, root string) (*Snapshot, error)

Load returns a defensive copy of the latest complete snapshot.

func (*MemoryStore) Status

func (store *MemoryStore) Status(ctx context.Context, root string) (Status, error)

Status reports whether a complete snapshot is present. Missing roots are represented by Present=false rather than an error so status is idempotent.

type PruneOptions

type PruneOptions struct {
	ObservedPaths     map[string]struct{}
	FullWalkSucceeded bool
}

PruneOptions makes the membership authority explicit. A narrow or failed walk must pass FullWalkSucceeded=false and therefore cannot delete entries.

type Snapshot

type Snapshot struct {
	SchemaVersion uint32
	Root          string
	Generation    uint64
	Entries       map[string]FileResult
}

Snapshot is a complete generation for one canonical root. The current directory walk remains authoritative; entries absent from that walk never contribute to an aggregate even if they remain in this snapshot.

type Status

type Status struct {
	Root          string
	Present       bool
	Failure       CacheFailureKind
	SchemaVersion uint32
	Generation    uint64
	Entries       int
	Bytes         int64
	ModifiedAt    time.Time
	Age           time.Duration
}

Status is the non-persistent store status for one canonical root.

type Store

Store is the narrow persistence boundary used by counting code. A cache failure must never replace a correctly computed count with an error; callers may treat load or commit-and-prune failures as cold-path or diagnostic conditions while explicit management operations can surface them directly.

type UpdateSet

type UpdateSet map[string]FileResult

UpdateSet contains per-file results. Methods may be a partial set when a run requests an additional tokenizer contract.

type ValidationMode

type ValidationMode uint8

ValidationMode controls how an existing entry is considered reusable.

const (
	// Metadata accepts a hit when normalized path, size, and nanosecond mtime match.
	Metadata ValidationMode = iota + 1
	// Verified reads and hashes the file, accepting a hit only when its digest matches.
	Verified
)

func (ValidationMode) String

func (m ValidationMode) String() string

type ValidationResult

type ValidationResult struct {
	Hit            bool
	Observation    FileObservation
	Digest         [sha256.Size]byte
	BytesRead      int64
	DigestDuration time.Duration
}

ValidationResult reports whether an entry can be reused and the work needed to reach that decision.

type ValidationStats

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

ValidationStats collects work measurements for one validation run.

func (*ValidationStats) Snapshot

Snapshot returns a race-free copy of the current measurements.

type ValidationStatsSnapshot

type ValidationStatsSnapshot struct {
	FilesChecked   int64
	Hits           int64
	Misses         int64
	FullReads      int64
	BytesRead      int64
	DigestDuration time.Duration
}

ValidationStatsSnapshot is an immutable view of ValidationStats.

type Validator

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

Validator validates entries without changing the production count path.

func NewValidator

func NewValidator(mode ValidationMode) (Validator, error)

NewValidator creates a validator for an experimental validation mode.

func (Validator) Validate

func (v Validator) Validate(ctx context.Context, root, path string, entry Entry, stats *ValidationStats) (ValidationResult, error)

Validate checks one current file against a previously captured entry. Metadata mode intentionally permits timestamp-preserving false hits; only Verified mode provides content identity for that adversarial case.

Jump to

Keyboard shortcuts

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