Skip to content

v1.9.1: Cold install overhaul, HTTP prefetch, and workspace fixes

Latest

Choose a tag to compare

@mise-en-dev mise-en-dev released this 07 May 00:00
· 5 commits to main since this release
Immutable release. Only release title and notes can be modified.
8e28ce5

A performance- and correctness-focused patch release. Cold installs get a streaming tarball pipeline, Linux gets an O_TMPFILE+linkat CAS fast path, and the resolver's cold path overlaps DNS, TLS, and packument prefetch with the manifest/workspace/lockfile work that used to serialize them. On the fix side, aube run once again finds node-gyp for package scripts, and aube update / aube outdated stop trying to fetch unpublished workspace: deps from the registry.

Added

  • Pre-resolver packument prefetch + shared HTTP utilities (#529 by @imjustprism) — a new aube-util::http module consolidates client-side primitives (prewarm, priority, race, resolve, ticket_cache) so leaf crates share one warm-pool surface with consistent killswitch semantics. On install entry, aube now reads package.json and fires fire-and-forget packument GETs for every registry-shaped direct dep before workspace yaml load, settings resolve, lockfile parse, and resolver construction — by the time the resolver pops its first task, the packument cache and reqwest pool are warm. RegistryClient::prewarm_connection now covers the default registry plus every scoped (@org:registry=...) and per-uri auth registry, with parallel DNS preresolve so DNS RTT hides behind the TLS handshake. Abbreviated packument GETs also send Priority: u=0 (RFC 9218 Critical) so H2 schedulers prioritize resolver-blocking metadata over pending tarball frames. New killswitches: AUBE_DISABLE_DNS_PRERESOLVE, AUBE_DISABLE_REQUEST_RACING, AUBE_DISABLE_PREFETCH, AUBE_DISABLE_TLS_TICKET_CACHE. Prefetch is a no-op when offline or when any lockfile is present.

  • Cold install pipeline overhaul (#522 by @imjustprism) — several overlapping wins on the cold-cache path:

    • Streaming tarball pipeline (opt-in via AUBE_TARBALL_STREAM=1, killswitch AUBE_DISABLE_TARBALL_STREAM) — HTTP body chunks pipe through SHA-512 + gz + tar + CAS via an mpsc bridge instead of buffering the whole tarball; non-SHA-512 SRI falls back to buffered. Bounded by the registry's tarball_max_bytes cap.
    • Linux O_TMPFILE + linkat CAS publish with EOPNOTSUPP fallback to the tempfile path, posix_fallocate to avoid ext4 fragmentation, and posix_fadvise(DONTNEED) to free page cache after publish. Killswitch: AUBE_DISABLE_O_TMPFILE.
    • Materialize-stream into the lockfile fast path — both lockfile and no-lockfile branches now share the GVS prewarm materializer, hiding 30-200ms of GVS reflinks behind the in-flight download tail.
    • Resolver tuning — foldhash on graph_hash hot maps, pre-sized resolver caches, thread-local node_semver::Version parse cache, PARALLEL_IMPORT_THRESHOLD lowered from 256 to 16 (median npm tarball is 7 files), and pinned tokio worker_threads (cpu.min(8)) / max_blocking_threads(64) (tunable via AUBE_TOKIO_WORKERS / AUBE_TOKIO_BLOCKING).
    • Windows gets FILE_ATTRIBUTE_NOT_CONTENT_INDEXED on the store root; cross-volume detection (drive letters on Windows, dev id on Unix) is gated per-platform.

    Reported same-volume Windows cold-install ratios: 1.80x-8.75x faster than Bun across svelte/vite/next/babylon.

  • Per-project materialize pipelined into fetch (#527 by @imjustprism) — when GVS is off, each fetched (canonical_key, PackageIndex) triggers materialize_into against .aube/<dep_path>/ immediately, so by the time fetch finishes the dedicated link phase only has to create top-level node_modules/<name> symlinks. The driver now uses JoinSet instead of Vec<JoinHandle>, so on early-return all in-flight tasks abort instead of detaching and racing install cleanup. ~10% improvement on warm fresh installs in the local benchmark matrix.

Fixed

  • aube run / aube test find node-gyp (#518 by @jdx) — package scripts only had node_modules/.bin prepended to PATH, so aube test would fail with node-gyp: not found on hosts that didn't already ship it. Script execution now reuses aube's existing node-gyp bootstrap (via a lazy shim bin dir + AUBE_NODE_GYP_EXE / AUBE_NODE_GYP_PROJECT_DIR), matching pnpm/npm behavior. Ports pnpm's lifecycleScripts.ts:128 coverage into the offline node-gyp bootstrap bats suite.

  • workspace: deps in aube update / aube outdated (#523 by @jdx, fixes #520) — aube update now discovers workspace package name/version pairs and passes them into resolver workspace resolution so workspace: deps from package.json#workspaces resolve locally instead of triggering registry packument fetches. aube outdated filters out direct deps with workspace: specifiers and reports "no matching dependencies" rather than attempting a packument fetch. Adds a new WARN_AUBE_WORKSPACE_PACKAGE_MISSING_NAME warning code for workspace packages without a name field.

  • Resolver peer-context divergence is fatal (#522 by @imjustprism) — apply_peer_contexts hitting MAX_ITERATIONS used to log a warning and ship a broken graph; it now returns a fatal Error::PeerContextDivergence(usize). state::remove_state errors at --force and GVS-transition sites also propagate instead of being silently swallowed, so permission-denied or Windows-locked sidecars no longer defeat the freshness check.

  • Tarball hardening (#522 by @imjustprism) — entries declared as 0 bytes with non-zero stream payload are now rejected (synthetic-entry injection guard), and GNU LongName / LongLink metadata records are correctly accepted.

  • Patches loaded once per cwd (#529 by @imjustprism) — load_patches_for_linker walked patches/ from disk 2-3 times per install (lockfile-prewarm, no-lockfile-prewarm, and link-phase sites). Now cached per cwd via OnceLock<Mutex<HashMap<PathBuf, ...>>>.

Full Changelog: v1.9.0...v1.9.1

💚 Sponsor aube

aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.

If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.