You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace soldr's current shell-out-to-zccache-bin compile dispatch with an in-process zccache::embedded::ZccacheService call. The MVP Rust API landed upstream in zccache v1.12.11 (crates/zccache/src/embedded.rs) — this issue tracks the soldr-side integration (zccache#907).
soldr shells out to zccache binary, one IPC roundtrip per compile (UDS on Linux/macOS, named pipe on Windows)
soldr calls service.compile(…) in its own Tokio runtime
Runtime
2 processes, 2 runtimes
1 process, 1 runtime
Audit
Cross-process stitching at the broker
soldr's run_id flows directly into zccache events
Compile dispatch latency
+ ~50–200 µs IPC roundtrip per command (Windows named pipes are the worst case)
Function call
The standalone zccache-daemon binary stays — drop-in CLI use unchanged. Embedded is an alternative front door, not a replacement.
Plan
Phase 1 — vendor for iteration
zccache::embedded may move during the integration. Don't lock to a crates.io version yet.
Add a git/path dep on zccache behind a embedded feature flag in soldr's main crate
Pin to a specific zccache commit; bump as needed during integration
Phase 2 — wrapper + dispatcher
Keep the upstream-API blast radius to one soldr-side type.
Add SoldrZccacheService — the only soldr module that imports zccache::embedded::*. Owns the ZccacheService handle and soldr's identity defaults
Add a tagged-enum dispatcher: enum CompileBackend { Embedded(Arc<SoldrZccacheService>), Wrapped(WrappedZccacheBin) }. Default Wrapped initially; flip the default after the parity test passes
Pick default audit mode (recommend normal for local, verbose for CI runs that emit build reports)
Document the mapping in soldr's design docs
Phase 4 — lifecycle wiring
ZccacheService::start once at soldr daemon startup; cache root at <soldr_cache_root>/zccache/
Expose service.stats() through soldr's existing diagnostics endpoint (so operators see hits/misses without a separate CLI roundtrip)
Call service.flush() from the "writing build report" phase
Call service.shutdown(ShutdownMode::Graceful) from the normal-exit path; Force from the abort path
Phase 5 — parity gate
CI test that runs the same compile through both backends and asserts byte-identical outputs (object file + stdout + stderr + exit code + cache outcome)
Flip the default backend to Embedded only after this passes on Linux + macOS + Windows
RuntimeHooks is a placeholder — currently { service_name: Option<String> }. Likely needs a tokio::runtime::Handle field or an explicit "use the calling runtime" contract before soldr depends on it. May warrant an upstream zccache PR.
Process-spawn priority sharing. zccache's CompilePriority::Auto ticket (PR zccache#919) consults zccache's own in-flight counter. When embedded, that counter doesn't know about soldr's own spawns. Decide whether to:
extend ServiceLimits with an external-counter knob upstream, or
document that the counter is zccache-internal-only and soldr accepts that.
Cancellation token plumbing. The embedded contract specifies host cancellation participation, but ZccacheConfig does not yet accept a CancellationToken. Additive upstream change.
Cache namespacing. Endpoint is derived from HostIdentity { product, instance_id, workspace_id }. soldr needs stable values across runs (for cache continuity) or explicit per-workspace opt-out.
Audit emission landing late. Schema is shipped; durable hot-path emission is still TBD upstream. Decide whether to ship the embedded transport first with audit as a no-op, or wait.
Risks
Upstream API churn during integration → mitigated by Phase 1 (vendor first).
Audit emission gap → first embedded soldr release may be "fast but no causal audit". Track explicitly.
Shared-runtime contention → soldr's existing async work now shares a Tokio runtime with zccache's compile/persist tasks. PR zccache#919's adaptive priority and perf(release): soldr binary is 16.3 MB (large tier); strip + lto could halve it #920's expanded pool sizing were designed for the standalone daemon; the same numbers may need re-tuning when both products share one runtime. Plan a measurement pass before flipping the default.
Summary
Replace soldr's current shell-out-to-
zccache-bincompile dispatch with an in-processzccache::embedded::ZccacheServicecall. The MVP Rust API landed upstream in zccache v1.12.11 (crates/zccache/src/embedded.rs) — this issue tracks the soldr-side integration (zccache#907).Anchor design doc:
docs/architecture/embedded-service.mdin the zccache repo.What soldr does today vs target
zccachebinary, one IPC roundtrip per compile (UDS on Linux/macOS, named pipe on Windows)service.compile(…)in its own Tokio runtimerun_idflows directly into zccache eventsThe standalone
zccache-daemonbinary stays — drop-in CLI use unchanged. Embedded is an alternative front door, not a replacement.Plan
Phase 1 — vendor for iteration
zccache::embeddedmay move during the integration. Don't lock to a crates.io version yet.embeddedfeature flag in soldr's main cratePhase 2 — wrapper + dispatcher
Keep the upstream-API blast radius to one soldr-side type.
SoldrZccacheService— the only soldr module that importszccache::embedded::*. Owns theZccacheServicehandle and soldr's identity defaultsenum CompileBackend { Embedded(Arc<SoldrZccacheService>), Wrapped(WrappedZccacheBin) }. Default Wrapped initially; flip the default after the parity test passesPhase 3 — audit context plumbing
Most invasive non-mechanical change.
AuditContext { run_id, trace_id, parent_span_id, command_id, session_id }normalfor local,verbosefor CI runs that emit build reports)Phase 4 — lifecycle wiring
ZccacheService::startonce at soldr daemon startup; cache root at<soldr_cache_root>/zccache/service.stats()through soldr's existing diagnostics endpoint (so operators see hits/misses without a separate CLI roundtrip)service.flush()from the "writing build report" phaseservice.shutdown(ShutdownMode::Graceful)from the normal-exit path;Forcefrom the abort pathPhase 5 — parity gate
Embeddedonly after this passes on Linux + macOS + WindowsPhase 6 — ship + measure
Open questions to resolve in Phase 1–2
RuntimeHooksis a placeholder — currently{ service_name: Option<String> }. Likely needs atokio::runtime::Handlefield or an explicit "use the calling runtime" contract before soldr depends on it. May warrant an upstream zccache PR.CompilePriority::Autoticket (PR zccache#919) consults zccache's own in-flight counter. When embedded, that counter doesn't know about soldr's own spawns. Decide whether to:ServiceLimitswith an external-counter knob upstream, orZccacheConfigdoes not yet accept aCancellationToken. Additive upstream change.HostIdentity { product, instance_id, workspace_id }. soldr needs stable values across runs (for cache continuity) or explicit per-workspace opt-out.Risks
What we do NOT change
zccache-daemonbinary stays — drop-in CLI users unaffected.soldr update-zccachestays — the perf-cluster path deliberately builds from source and does not use the embedded service (see PERF.md).Suggested first PR shape
One PR behind
--features embedded:SoldrZccacheServiceand theCompileBackendenum (default Wrapped).SOLDR_ZCCACHE_EMBEDDED=1) so early adopters can flip the backend at runtime without rebuilding.The parity-gate PR (Phase 5) is what flips the default backend in a later release.
Definition of done
SoldrZccacheServicewrapper exists in soldrCompileBackend::{Embedded, Wrapped}enum in the dispatcherUpstream references
v1.12.11release: https://github.com/zackees/zccache/releases/tag/1.12.11