mirror of
https://github.com/pnpm/pnpm.git
synced 2026-07-30 01:16:56 -04:00
315e59b24acfe9e0ec0f56ffce1cb75927586bf4
Backfills two channels from #347 in one PR — both are "progress" shaped so they share the tarball-side reporter threading. ### `pnpm:progress` — per-package status transitions Mirrors pnpm's emit at [`installing/package-requester/src/packageRequester.ts:435`](https://github.com/pnpm/pnpm/blob/086c5e91e8/installing/package-requester/src/packageRequester.ts#L435). Four `status` values fire per package: - **`resolved`** — emitted before the tarball download in both lockfile paths. In the no-lockfile path, `install_package_from_registry::run` emits once the registry has picked a version. In the frozen-lockfile path, `create_virtual_store::run`'s warm batch and per-snapshot `install_package_by_snapshot::run`'s entry emit on each snapshot (the lockfile *is* the resolution). - **`fetched`** — emitted from `fetch_and_extract_with_retry` on the successful `Ok` branch. Failed attempts that retry don't fire it; cache-hit early returns don't fire it. - **`found_in_store`** — emitted from `run_without_mem_cache`'s cache-hit early returns (prefetched-cas + `load_cached_cas_paths`), from `create_virtual_store::run`'s warm batch where prefetch already settled the bytes, and from `run_with_mem_cache`'s in-process dedup hits (so the second requester of a shared URL also ticks the per-package counter). - **`imported`** — emitted after `create_cas_files` returns `Ok` in both `create_virtual_dir_by_snapshot::run` and `install_package_from_registry::install_package_version`. `method` is the optimistic wire-mapped configured method (`Auto`/`CloneOrCopy` → `clone`); pacquet doesn't surface the per-package resolved method past `link_file`'s install-scoped atomic. Tracked under #347 for refinement once that becomes per-package observable. ### `pnpm:fetching-progress` — per-tarball download progress Mirrors pnpm's emit at [`installing/package-requester/src/packageRequester.ts:560`](https://github.com/pnpm/pnpm/blob/086c5e91e8/installing/package-requester/src/packageRequester.ts#L560) and [`fetching/tarball-fetcher/src/remoteTarballFetcher.ts:143`](https://github.com/pnpm/pnpm/blob/086c5e91e8/fetching/tarball-fetcher/src/remoteTarballFetcher.ts#L143). Two `status` values: - **`started`** — fires exactly once per HTTP attempt, including attempts that fail before the response head arrives (DNS / connect / timeout) so retried attempts stay visible in the reporter. `size` is the response's `Content-Length` when a response head arrives, and JSON `null` (i.e. `None`) when there is no response, or when the response is chunked / unknown-length. pnpm's reporter checks `size != null` before rendering a percent gauge. - **`in_progress`** — gated and throttled to match pnpm exactly: - Skip entirely when `Content-Length` is unknown (chunked / streaming) or the tarball is smaller than `BIG_TARBALL_SIZE = 5 MB`. Most npm packages are well under this; per-byte progress for tiny tarballs floods the JS reporter with values that would render as 100% before any UI tick can show them. - Throttle to 500ms (matches `lodash.throttle(opts.onProgress, 500)`). - Trailing edge: a final emit after the body finishes if the last in-flight `downloaded` value differs from the last reported one. Matches `lodash.throttle`'s default `{leading: true, trailing: true}` so the consumer sees the actual end-of-download byte count. ### `run_with_mem_cache` deadlock fix Pre-existing bug exposed by review: when the *owning* requester's `run_without_mem_cache` errored, the function returned without flipping the cache slot to `Available` or notifying waiters. Concurrent siblings parked on `notify.notified().await` forever and the install hung — a single 404 could deadlock every later consumer of the same URL. Fixed by adding `CacheValue::Failed`. The owner uses `match` on the result; on `Err` it sets `Failed`, removes the entry from `mem_cache` (so a fresh request can retry without inheriting the failure), and notifies waiters. Waiters check for `Failed` on wake and surface a new `TarballError::SiblingFetchFailed { url }` instead of the `unreachable!` the previous code would have hit. ### Threading `pacquet-tarball` gains a `pacquet-reporter` dependency. `DownloadTarballToStore` carries a new `requester: &'a str` field (the install root, same value as the `prefix` in `pacquet_reporter::StageLog`). `<R: Reporter>` is threaded through `run_with_mem_cache`, `run_without_mem_cache`, `fetch_and_extract_with_retry`, and `fetch_and_extract_once`. The generic monomorphises away — zero runtime cost. `requester` and `<R>` cascade up through `InstallPackageBySnapshot`, `InstallPackageFromRegistry`, `CreateVirtualDirBySnapshot`, `CreateVirtualStore`, `InstallFrozenLockfile`, `InstallWithoutLockfile`, and `Install::run`.
Description
Languages
Rust
63.2%
TypeScript
36.3%
JavaScript
0.4%