Skip to content

Commit c99f30d

Browse files
committed
Speculative parallel prefetch of transitive dependencies
Before running the solver, prefetch the entire dependency tree breadth-first with 16 concurrent HTTP requests. Uses only the latest stable version's deps to avoid fetching every version.
1 parent 6cf041c commit c99f30d

1 file changed

Lines changed: 15 additions & 4 deletions

File tree

lib/npm/resolver.ex

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ defmodule NPM.Resolver do
99
@behaviour HexSolver.Registry
1010

1111
@table :npm_resolver_cache
12+
@max_nesting_depth 5
13+
@max_prefetch_depth 10
14+
@prefetch_concurrency 16
15+
@fetch_timeout 30_000
1216

1317
@doc """
1418
Resolve a set of root dependencies to exact versions.
@@ -44,7 +48,8 @@ defmodule NPM.Resolver do
4448
end
4549
end
4650

47-
defp resolve_with_nesting(_root_deps, _excluded, _nested, depth) when depth > 5 do
51+
defp resolve_with_nesting(_root_deps, _excluded, _nested, depth)
52+
when depth > @max_nesting_depth do
4853
{:error, "Too many resolution retries — deeply conflicting dependencies"}
4954
end
5055

@@ -234,7 +239,10 @@ defmodule NPM.Resolver do
234239
packages
235240
|> Enum.map(fn {_repo, name} -> name end)
236241
|> Enum.reject(&cached?/1)
237-
|> Task.async_stream(&fetch_and_cache/1, max_concurrency: 8, timeout: 30_000)
242+
|> Task.async_stream(&fetch_and_cache/1,
243+
max_concurrency: @prefetch_concurrency,
244+
timeout: @fetch_timeout
245+
)
238246
|> Stream.run()
239247

240248
:ok
@@ -332,14 +340,17 @@ defmodule NPM.Resolver do
332340
end
333341

334342
defp prefetch_tree(packages, depth \\ 0)
335-
defp prefetch_tree(_packages, depth) when depth > 10, do: :ok
343+
defp prefetch_tree(_packages, depth) when depth > @max_prefetch_depth, do: :ok
336344

337345
defp prefetch_tree(packages, depth) do
338346
to_fetch = Enum.reject(packages, &cached?/1)
339347

340348
if to_fetch != [] do
341349
to_fetch
342-
|> Task.async_stream(&fetch_and_cache/1, max_concurrency: 16, timeout: 30_000)
350+
|> Task.async_stream(&fetch_and_cache/1,
351+
max_concurrency: @prefetch_concurrency,
352+
timeout: @fetch_timeout
353+
)
343354
|> Stream.run()
344355

345356
next_level =

0 commit comments

Comments
 (0)