Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Why Is It Designed This Way?

Why use a resident local server?

Short-lived compiler wrappers can share discovered compiler state, statistics, remote clients, storage connections, and a machine-wide process budget without requiring every build tool to embed them.

Why hash preprocessed inputs instead of command text alone?

The output depends on headers, environment, compiler identity, flags, and other implicit inputs. A fast but incomplete key would return incorrect artifacts.

Why separate compiler parsing from hashing and execution?

Recognition chooses the family; parsed invocation state then owns the expensive async path. Unsupported invocations can fall through without contaminating the shared server architecture with compiler-specific branches.

Why return a cache-write future with a miss?

The compiler result is latency-sensitive; making it reusable is a related background obligation. Carrying the future preserves tracking without forcing artifact upload into the compiler’s critical response path.

Why have a jobserver in addition to Tokio?

Tokio schedules futures, not CPU budgets consumed by rustc subprocesses that may themselves use threads. A token models the scarce external resource.

Why use trait objects for storage and compilers?

Their concrete types are selected from runtime configuration and executable discovery. Static monomorphization cannot place unrelated implementations in the same server maps without an enum that must change for every extension.

Why is shutdown ownership-based?

An incremented counter can miss an error path. Strong ActiveInfo ownership already exactly describes live services; the weak waiter derives completion from that fact.