Layering Strategy for Repository Caching in Worktrunk: Two-Layer Architecture Explained
Worktrunk employs a dual-layer caching strategy that combines process-wide static caches for expensive operations with per-repository RepoCache instances to memoize Git data within a single CLI command.
Worktrunk, a Rust-based Git utility, implements a sophisticated layering strategy for repository caching that optimizes CLI performance while preventing stale state across invocations. The architecture strategically separates long-lived process-wide caches from short-lived per-command repositories, ensuring that expensive Git operations are memoized efficiently without risking outdated data persistence between separate runs.
The Two-Layer Caching Architecture
Worktrunk's caching strategy operates across two distinct layers with different lifetimes and scopes, defined primarily in src/git/repository/mod.rs.
Process-Wide Static Caches (Global)
The first layer consists of process-wide static caches that persist for the entire lifetime of the Worktrunk process. These caches utilize static OnceCells and DashMaps initialized at the module level in src/git/repository/mod.rs (lines 22–28). This layer stores expensive-to-compute values that remain valid across multiple CLI commands, such as remote-default-branch lookups that may require network requests. By retaining this data in static memory, Worktrunk avoids redundant network calls when users execute multiple commands in sequence.
Per-Repository RepoCache (Command-Scoped)
The second layer comprises the per-repository RepoCache structure that exists only for the duration of a single CLI command. When Repository::at() is called, it instantiates a fresh RepoCache wrapped in an Arc (lines 229–243 in src/git/repository/mod.rs), allowing many Repository clones to share the same cache safely across threads. This layer stores command-scoped data including branch lists, worktree listings, remote URLs, and SHA lookups. Since a new RepoCache is created for each command invocation, this layer guarantees that stale data never persists across separate Worktrunk runs.
Implementation Details and Code Flow
The interaction between these layers follows a strict hierarchy to maximize performance while maintaining consistency. When a command initiates, Repository::at() constructs a fresh RepoCache instance. All subsequent Git data requests first check this per-repository cache; if the entry is missing, the system populates it and stores the result for the remainder of the command.
For data that is prohibitively expensive to re-fetch across commands, the implementation falls back to the process-wide static cache. For example, the default_branch() method checks the static cache before performing network operations, ensuring that subsequent commands reuse the cached result without additional I/O.
// src/git/repository/mod.rs
// Repository::at() creates a fresh RepoCache for each command
let repo = Repository::at(&path)?;
// First call scans git and caches in RepoCache
let worktrees = repo.list_worktrees()?; // hits filesystem
// Second call retrieves from per-repo cache
let worktrees_again = repo.list_worktrees()?; // fast, from Arc<RepoCache>
// Remote default branch uses process-wide static cache
let default = repo.default_branch()?; // may use static OnceCell
Cache Consistency and Invalidation
The layering strategy eliminates complex cache invalidation by leveraging Rust's ownership model and command-scoped lifetimes. The per-repository cache requires no explicit invalidation because Repository::at() creates a new RepoCache for every CLI invocation. When the command terminates and the Repository drops, the cache disappears automatically.
The process-wide static cache intentionally stores only immutable data that remains valid for the process duration, such as remote repository metadata. Since these values do not change without external network updates, the static cache persists safely across commands without invalidation logic.
Key Source Files
| File | Purpose |
|---|---|
src/git/repository/mod.rs |
Defines RepoCache structure and static caches (lines 229–243) |
src/git/repository/config.rs |
Implements remote-default-branch caching using static stores |
src/git/repository/branches.rs |
Branch enumeration logic utilizing per-repo cache |
src/git/repository/worktrees.rs |
Worktree listing cached in RepoCache |
Summary
- Worktrunk uses two distinct cache layers: process-wide static caches for expensive cross-command data and per-repository
RepoCachefor command-scoped memoization. - Static caches in
src/git/repository/mod.rsleverageOnceCellandDashMapto store network-expensive values like remote default branches across the entire process lifetime. - Per-repo caches are instantiated fresh by
Repository::at()for each command, wrapped inArcfor thread-safe sharing, and automatically invalidated when the command completes. - This architecture delivers high-performance Git operations while guaranteeing that no stale repository state persists between separate Worktrunk invocations.
Frequently Asked Questions
What is the RepoCache struct in Worktrunk?
RepoCache is a thread-safe caching structure defined in src/git/repository/mod.rs that stores Git metadata for the duration of a single CLI command. It contains OnceCells and DashMaps wrapped in an Arc, allowing multiple Repository clones to share cached branch lists, worktree information, and SHA lookups without redundant git subprocess calls.
How does Worktrunk prevent stale cache data between commands?
Worktrunk prevents stale data by creating a fresh RepoCache instance every time Repository::at() is called at the start of a command. Since the cache is command-scoped and dropped when the command completes, subsequent invocations always start with empty caches, eliminating the risk of stale reads across CLI runs.
What data is stored in the process-wide static cache?
The process-wide static cache stores expensive-to-compute values that remain valid for the process lifetime, specifically network-dependent metadata such as remote-default-branch lookups. These values are stored in static OnceCells in src/git/repository/mod.rs (lines 22–28) to avoid redundant network requests across multiple Worktrunk commands executed in sequence.
Why does Worktrunk use Arc to wrap RepoCache?
Worktrunk wraps RepoCache in an Arc (atomic reference counter) to enable safe sharing across multiple Repository clones within the same command. Since Repository instances are frequently cloned during Git operations, the Arc ensures all clones access the same underlying cache data without copying the cache structure, maintaining consistency while avoiding unnecessary memory allocation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →