Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
225 commits
Select commit Hold shift + click to select a range
315391a
perf(core): add an ordered, bounded concurrency helper for API loops
mikolalysenko Sep 24, 2026
148a32d
test(scan): pin API-loop ordering under reversed latencies
mikolalysenko Sep 24, 2026
113df71
perf(scan): fetch per-package patch details concurrently
mikolalysenko Sep 24, 2026
04a730c
perf(scan): run batch discovery concurrently with exact proxy fallback
mikolalysenko Sep 24, 2026
cab7007
perf(hosted): fetch patch record views concurrently on wet runs
mikolalysenko Sep 24, 2026
fc03c9e
perf(scan): send telemetry off the critical path, flushed before exit
mikolalysenko Sep 24, 2026
cf6f20c
fix(scan): deliver background telemetry before the first stdout write
mikolalysenko Sep 24, 2026
0636854
refactor(telemetry): share the patch_scan_failed metadata builder
mikolalysenko Sep 24, 2026
5904769
refactor(core): keep the collecting concurrency helper test-only
mikolalysenko Sep 24, 2026
b3565c0
perf(crawl): walk npm trees on the blocking pool with parallel gather…
mikolalysenko Sep 24, 2026
c13eae6
perf(crawl): find_by_purls lists each node_modules once and probes on…
mikolalysenko Sep 24, 2026
b5dc36d
perf(crawl): run the nine ecosystem crawlers concurrently
mikolalysenko Sep 24, 2026
c098289
perf(crawl): resolve find_by_purls one BFS level at a time
mikolalysenko Sep 24, 2026
b89f1cd
test(crawl): keep the oracle fixture generator warning-free on non-Un…
mikolalysenko Sep 24, 2026
fe7f385
style(crawl): keep the test-only oracle module out of the npm crawler…
mikolalysenko Sep 24, 2026
2681425
fix(crawl): walk workspace roots level by level instead of recursing
mikolalysenko Sep 24, 2026
58f5942
fix(crawl): run npm walks on a main-sized stack within the descriptor…
mikolalysenko Sep 24, 2026
8de0602
perf(redirect): parse each pnpm lock once and splice in one pass
mikolalysenko Sep 24, 2026
1ce8ed4
perf(hosted): probe Python locks once and fetch wheel metadata concur…
mikolalysenko Sep 24, 2026
ba64f3e
perf(redirect): derive npm and yarn-classic entry identities once per…
mikolalysenko Sep 24, 2026
f1b0ca1
test(redirect): pin the pnpm residual boundaries on the production gate
mikolalysenko Sep 24, 2026
ed0c785
perf(hosted): cap wheel-metadata fetches at 4 and test that they overlap
mikolalysenko Sep 24, 2026
029e179
perf(scripts): add a record/replay network benchmark harness
mikolalysenko Sep 24, 2026
a82079a
test(scripts): cover the perf record/replay harness offline
mikolalysenko Sep 24, 2026
62dc8c5
refactor(hosted): fetch wheel metadata through the shared ordered_con…
mikolalysenko Sep 24, 2026
ef34d36
fix(scan): deliver background telemetry before the first stderr write…
mikolalysenko Sep 24, 2026
5623fbf
docs(telemetry): say why the inline scan trackers stay public
mikolalysenko Sep 24, 2026
42675ec
test(scan): pin that the mid-run fallback discards in-flight answers
mikolalysenko Sep 24, 2026
90616df
perf(api): share one in-flight cap across concurrent proxy batch calls
mikolalysenko Sep 24, 2026
e183bc5
fix(crawl): never fall back to rayon's global pool when walk threads …
mikolalysenko Sep 24, 2026
b563c2c
test(crawl): pin the store-entry identity_seen skip against the oracle
mikolalysenko Sep 24, 2026
c85bbd7
test(crawl): pin the resolver probe filter's always-probe components
mikolalysenko Sep 24, 2026
b41efed
test(cli): pin the one-at-a-time crawler dispatch under a tight fd limit
mikolalysenko Sep 24, 2026
4e9d3ec
perf(hosted): settle only first attempts concurrently, retry wheels s…
mikolalysenko Sep 24, 2026
25a5795
test(redirect): require the random pnpm sweep to reach every outcome
mikolalysenko Sep 24, 2026
9c5d3e7
perf(scripts): let bench.sh take explicit ports and refuse busy ones
mikolalysenko Sep 24, 2026
167f684
fix(scan): request one at a time under a tight descriptor limit
mikolalysenko Sep 24, 2026
59d5e25
perf(get): fetch patch views concurrently ahead of the download loop
mikolalysenko Sep 24, 2026
ca9c2f6
perf(vendor): reuse scan's npm crawl instead of walking node_modules …
mikolalysenko Sep 24, 2026
ed3d423
perf(vendor): prefetch service downloads ahead of the serial wiring loop
mikolalysenko Sep 24, 2026
ba70325
perf(vendor): fetch lockfile-only packages from their registries conc…
mikolalysenko Sep 24, 2026
1aca5f3
fix(scan): end the batch window instead of re-running it
mikolalysenko Sep 25, 2026
01c3573
feat(api): let SOCKET_API_CONCURRENCY pace the patch-API windows
mikolalysenko Sep 25, 2026
d46d4a5
perf(scan): open the proxy batch window at the first chunk
mikolalysenko Sep 25, 2026
b8b3123
perf(hosted): keep records, not whole payloads, in the view window
mikolalysenko Sep 25, 2026
22603e4
refactor(telemetry): one prepared-event builder per scan event
mikolalysenko Sep 25, 2026
eab81f2
perf(crawl): record only the targets a resolver visit matched
mikolalysenko Sep 25, 2026
9490b04
fix(crawl): skip the main-sized-stack probe when no walk pool exists
mikolalysenko Sep 25, 2026
f8c01bc
docs(crawl): peak memory now scales with the walk thread count too
mikolalysenko Sep 25, 2026
cbfa45d
test(cli): name the descriptor budget when a tight-limit scan drops p…
mikolalysenko Sep 25, 2026
fa9122b
test(cli): give the ecosystem-order fixture an install in all nine
mikolalysenko Sep 25, 2026
3eec069
docs(crawl): say what the parallel gather costs, not only what it buys
mikolalysenko Sep 25, 2026
6446407
fix(hosted): resume a deferred wheel attempt, never restart its budget
mikolalysenko Sep 25, 2026
7955356
test(redirect): compare every RewriteResult channel from one shared o…
mikolalysenko Sep 25, 2026
a0e8466
perf(vendor): hand back slices from the pnpm key-line parser
mikolalysenko Sep 25, 2026
526fc4f
style(vendor): drop the rustfmt churn this work package never asked for
mikolalysenko Sep 25, 2026
58db437
fix(api): bound the vendor prefetch by what the loop has reached
mikolalysenko Sep 25, 2026
a9d64ee
fix(vendor): honor the one-request-at-a-time escape hatch in the pref…
mikolalysenko Sep 25, 2026
a4103ea
perf(vendor): pace registry downloads with a cap of their own
mikolalysenko Sep 25, 2026
218b6d8
fix(cli): check that a prefetched view belongs to the patch taking it
mikolalysenko Sep 25, 2026
39b4e17
refactor(ui): ask prompt whether a confirm waits, instead of re-deriv…
mikolalysenko Sep 25, 2026
de4afaa
refactor(crawl): make a new crawler option a compile error in the sna…
mikolalysenko Sep 25, 2026
ab9ab19
perf(scan): keep the npm crawl snapshot only where it is read
mikolalysenko Sep 25, 2026
50f9484
perf(vendor): keep fewer whole archives in memory than the API allows
mikolalysenko Sep 25, 2026
4affced
test(api): pin what a package the loop refuses costs in requests
mikolalysenko Sep 25, 2026
df28dc3
fix(hosted): pace the wheel-metadata window with the documented knob
mikolalysenko Sep 25, 2026
128e4e5
perf(vendor): stop the download plan amplifying an outage
mikolalysenko Sep 25, 2026
3563380
refactor(api): hold back every concurrent window's debug lines
mikolalysenko Sep 25, 2026
8c3faea
perf(crawl): cap the walk pool at what an I/O-bound walk can use
mikolalysenko Sep 25, 2026
f78bb39
docs(changelog): name what the concurrency work costs the service
mikolalysenko Sep 25, 2026
78c8293
fix(vex): pace the record fetch with the documented knob
mikolalysenko Sep 25, 2026
10b8969
perf(redirect): bound the Cargo.lock block search to the next block
mikolalysenko Sep 24, 2026
7ec7e7a
perf(build): use the aarch64 SHA-256 instructions
mikolalysenko Sep 24, 2026
f52e089
perf(maven): stop allocating per line in the POM coordinate parser
mikolalysenko Sep 24, 2026
4d98f6a
perf(gem): ask `gem env` once per process environment
mikolalysenko Sep 24, 2026
e209d30
perf(copy_tree): stop re-creating every file's parent in fresh_copy
mikolalysenko Sep 24, 2026
5f83276
perf(poetry): hand the rewrite's edits back instead of re-deriving them
mikolalysenko Sep 24, 2026
153ff3d
perf(pdm): hand the rewrite's edits back instead of re-deriving them
mikolalysenko Sep 24, 2026
130cc7e
fix(gem): keep only a complete `gem env` answer in the memo
mikolalysenko Sep 24, 2026
ba6458a
test(copy_tree): pin on-demand parents and the outer skip depth
mikolalysenko Sep 24, 2026
8d12fd6
test(poetry,pdm): cover the re-derived edits of a differing splice
mikolalysenko Sep 24, 2026
6dbdff8
docs(build): say which aarch64 SHA-256 path the asm feature selects
mikolalysenko Sep 24, 2026
4fcff74
perf(redirect): parse each uv/pylock/PEP 723 lock once per hosted rew…
mikolalysenko Sep 24, 2026
a905780
perf(redirect): read go.mod once per dep and join go.sum once per hos…
mikolalysenko Sep 24, 2026
b120a79
perf(redirect): splice composer.lock edits in place and skip other pa…
mikolalysenko Sep 24, 2026
5b869f9
perf(poetry): parse each poetry.lock state once across a hosted rewrite
mikolalysenko Sep 24, 2026
506cfe8
perf(pdm): parse each pdm.lock state once across a hosted rewrite
mikolalysenko Sep 24, 2026
36c6dc5
perf(crawl): walk the Go module cache in one blocking-pool task
mikolalysenko Sep 24, 2026
ca4bbcd
perf(crawl): read crate manifests in parallel on the walk pool
mikolalysenko Sep 24, 2026
d166538
perf(crawl): scan NuGet package dirs on the walk pool, list the root …
mikolalysenko Sep 24, 2026
af27d44
perf(crawl): read site-packages METADATA in parallel on the walk pool
mikolalysenko Sep 24, 2026
b91fe4e
perf(hosted): judge stale installs in one pass and look copies up onc…
mikolalysenko Sep 24, 2026
00914b4
perf(crawl): batch composer package stats and memo `composer global c…
mikolalysenko Sep 24, 2026
220e9c8
perf(crawl): parse the local Maven repository's POMs in parallel
mikolalysenko Sep 24, 2026
f19c760
perf(hosted): start the Pipenv probe before the wheel metadata fetch …
mikolalysenko Sep 24, 2026
595cb6e
perf(crawl): scan cargo, NuGet and site-packages dirs on one blocking…
mikolalysenko Sep 24, 2026
0977a71
fix(crawl): parse POMs through par_map, never rayon's global pool
mikolalysenko Sep 25, 2026
ec396a9
fix(composer): keep only a complete `composer global config home` answer
mikolalysenko Sep 25, 2026
ffa27b9
fix(crawl): memoize a directory listing only when it is the whole dir…
mikolalysenko Sep 25, 2026
abefdad
test(nuget): pin the case-insensitive legacy fallback and its reused …
mikolalysenko Sep 25, 2026
3d76160
test(hash): pin the blocking git-sha256 reader's size-mismatch refusals
mikolalysenko Sep 25, 2026
b24c865
test(vex): assert the judge's stale evidence on verified records too
mikolalysenko Sep 25, 2026
a156a83
perf(hosted): ask for a Pipfile.lock before listing what would target it
mikolalysenko Sep 25, 2026
13893de
refactor(crawl): write the dist-info name fallback once for both readers
mikolalysenko Sep 25, 2026
7cd6f0b
perf(crawl): bound the Maven scan's buffers to a chunk of the walk
mikolalysenko Sep 25, 2026
bb4f172
perf(vendor): rebuild local jars and nupkgs from memory, not a disk s…
mikolalysenko Sep 25, 2026
c2ead33
perf(vendor): build the patched wheel from one read of the installed …
mikolalysenko Sep 25, 2026
1b64359
fix(vendor): let the sidecar fixup's own paths through the repack nam…
mikolalysenko Sep 25, 2026
6c0567a
refactor(vendor): one definition of the NuGet sidecar's package-root …
mikolalysenko Sep 25, 2026
4252c8b
fix(vendor): fold every path component in the repack name gate
mikolalysenko Sep 25, 2026
9e5220f
fix(vendor): keep names the filesystem cannot store off the in-memory…
mikolalysenko Sep 25, 2026
d03be4d
fix(vendor): give the staged patch targets one order, not the HashMap's
mikolalysenko Sep 25, 2026
2686265
test(vendor): prove which staging each local-rebuild run took
mikolalysenko Sep 25, 2026
8f581dd
docs(vendor): say what a local rebuild actually materialises
mikolalysenko Sep 25, 2026
67b8e88
test(vendor): pin where a repeated archive name collapses
mikolalysenko Sep 25, 2026
e7db570
perf(vendor): extract a fetched package only where something reads it
mikolalysenko Sep 25, 2026
57b0560
perf(pypi): digest the prebuilt wheel where its bytes are already ver…
mikolalysenko Sep 25, 2026
3473fce
perf(vendor): write a fetched package's tree where the build wants it
mikolalysenko Sep 25, 2026
1fd364a
perf(vendor): inflate a zip's entries on a bounded pool, not one at a…
mikolalysenko Sep 25, 2026
67a95a6
style(vendor): undo two rewraps rustfmt made outside the files I touched
mikolalysenko Sep 25, 2026
068d23c
perf(vendor): spread a zip's entries only when there is inflating to do
mikolalysenko Sep 25, 2026
330cb10
fix(vendor): decide a zip's destinations from the archive, not from P…
mikolalysenko Sep 25, 2026
2f76cbc
perf(vendor): free a fetched archive's bytes once its tree is on disk
mikolalysenko Sep 25, 2026
f5cfb10
fix(vendor): report a stage's clear/create failure as the copy report…
mikolalysenko Sep 25, 2026
8dddeae
perf(service): digest a service archive only where something reads it
mikolalysenko Sep 25, 2026
c55cc8e
fix(cli): surface a pristine source that cannot be materialised
mikolalysenko Sep 25, 2026
1784bbe
perf(vendor): let a fetched archive go when the loop moves past its purl
mikolalysenko Sep 25, 2026
c3d82fd
fix(cli): raise one failure for a source that cannot be materialised
mikolalysenko Sep 25, 2026
16525ee
perf(vendor): seek a zip artifact's needed members by name
mikolalysenko Sep 25, 2026
e6cde90
perf(composer): parse composer.lock once per run, not once per package
mikolalysenko Sep 25, 2026
c850776
perf(cargo): parse Cargo.lock and the cargo config once per run
mikolalysenko Sep 25, 2026
d63b9e2
perf(vendor): let a parse memo keep a slot per file it is asked about
mikolalysenko Sep 25, 2026
9c6468a
perf(nuget): parse packages.lock.json once per run
mikolalysenko Sep 25, 2026
116b905
perf(pypi): parse each flavor's lock and project file once per run
mikolalysenko Sep 25, 2026
162d385
perf(vendor): digest an artifact off the async thread
mikolalysenko Sep 25, 2026
f781010
perf(pypi): list a project venv once per run for the pipenv stale probe
mikolalysenko Sep 25, 2026
5d1868f
perf(npm,yarn): parse the JS lockfiles once per run
mikolalysenko Sep 25, 2026
3d0e34c
perf(npm): hand the memo the lock a package just wrote
mikolalysenko Sep 25, 2026
12f3cb6
test(npm): pin that a restored lock between two packages misses the memo
mikolalysenko Sep 25, 2026
96ab6e9
docs(nuget): give the lock rewriter its own doc comment back
mikolalysenko Sep 25, 2026
9e1faae
style(yarn): put berry's memo static below the import block
mikolalysenko Sep 25, 2026
92277d7
test(vendor): pin the by-name zip harvest to the scan it replaced
mikolalysenko Sep 25, 2026
e908802
test(cargo,composer): pin a memoized run to an always-reparsing one
mikolalysenko Sep 25, 2026
c91d7e5
perf(cargo): keep a memo slot per cargo config spelling
mikolalysenko Sep 25, 2026
010187f
perf(npm): drop only the lock slots a package is about to write
mikolalysenko Sep 25, 2026
0115fb4
perf(yarn): stop memoizing the lock text the splice loop is building
mikolalysenko Sep 25, 2026
7ad3f5a
perf(uv): drop the lock's parse where wire writes the lock
mikolalysenko Sep 25, 2026
41fd32f
perf(hatch): parse the vendor ledger once per run, not once per package
mikolalysenko Sep 25, 2026
71b5a91
docs(vendor): say what the memos retain and what the venv listing giv…
mikolalysenko Sep 25, 2026
7bd1727
test(npm): pin the second pass over a lock npm 12 added after wiring
mikolalysenko Sep 25, 2026
3b5a4b0
style(vendor): undo the rewrap rustfmt made outside this change
mikolalysenko Sep 25, 2026
9d911c4
perf(vendor): let each npm flavor's pre-flight answer for the downloa…
mikolalysenko Sep 25, 2026
03546d3
perf(vendor): plan only the downloads the loop will ask for
mikolalysenko Sep 25, 2026
7502ac2
docs(changelog): the download plan is exact
mikolalysenko Sep 25, 2026
9e736f4
refactor(vendor): name what the binary Bun pre-flight hands the vendo…
mikolalysenko Sep 25, 2026
9f161b4
perf(vendor): guard a package's coordinates before the plan reads its…
mikolalysenko Sep 25, 2026
fb21ab5
test(vendor): pin the bun.lockb pre-flight against its own loop
mikolalysenko Sep 25, 2026
7e0a6cc
test(cli): fail the zero-grant test loudly when no plan can be built
mikolalysenko Sep 25, 2026
a43f24c
docs(vendor): point the plan's readers at the exact plan
mikolalysenko Sep 25, 2026
57a0d0c
fix(vendor): read the download plan's JS locks through the run's memos
mikolalysenko Sep 25, 2026
86f2508
perf(maven): take canonical POM coordinates from the ~/.m2 path
mikolalysenko Sep 25, 2026
1181fcd
perf(scan): crawl only the ecosystems --ecosystems names unless pruning
mikolalysenko Sep 25, 2026
4e88d58
style(cli/scan): revert rustfmt reflows of lines MVN-4 does not touch
mikolalysenko Sep 25, 2026
b1ac652
docs(cli): point the npm crawl snapshot at its production entry point
mikolalysenko Sep 25, 2026
7d6a386
fix(maven): confirm the scan root before taking coordinates from the …
mikolalysenko Sep 25, 2026
af3d4b9
test(cli/scan): pin the crawl-scope decision and the GC run's full crawl
mikolalysenko Sep 25, 2026
b29e083
feat(vendor): a pristine source whose download waits for its first read
mikolalysenko Sep 25, 2026
9c4e582
perf(vendor): skip the pristine download when nothing will read it
mikolalysenko Sep 25, 2026
d078a6d
docs(vendor): record the deferred pristine download
mikolalysenko Sep 25, 2026
d783329
feat(fs): one durability barrier for content-verified artifacts
mikolalysenko Sep 25, 2026
337bf55
perf(vendor): write vendored artifacts without a per-file fsync
mikolalysenko Sep 25, 2026
eda3050
docs(vendor): record the artifact durability barrier
mikolalysenko Sep 25, 2026
bcc4a33
feat(fs): capture a run's commit points and commit them through a jou…
mikolalysenko Sep 25, 2026
2736d39
perf(vendor): commit a vendored run's lockfile and ledger edits once
mikolalysenko Sep 25, 2026
055faee
docs(vendor): record the group commit and its crash semantics
mikolalysenko Sep 25, 2026
f790f23
perf(fs): hold a captured ledger as a value until something reads it
mikolalysenko Sep 25, 2026
c9a3680
feat(vendor): a snapshot table for the ledger's whole-file wiring texts
mikolalysenko Sep 25, 2026
48528e7
perf(vendor): store whole-file wiring snapshots once per file
mikolalysenko Sep 25, 2026
549d7c2
docs(vendor): record ledger schema version 2
mikolalysenko Sep 25, 2026
81b7468
fix(vendor): defer a cargo crate behind the service only when the reg…
mikolalysenko Sep 25, 2026
b1c9b0c
fix(vendor): trust a committed file artifact for the deferral only wh…
mikolalysenko Sep 25, 2026
aa8954e
fix(vendor): let a gem --dry-run keep its preview, and keep the backe…
mikolalysenko Sep 25, 2026
8028087
test(vendor): pin a deferred fetch's report ahead of the package's ow…
mikolalysenko Sep 25, 2026
5c173d6
fix(vendor): keep each whole-file snapshot edit inside its own record
mikolalysenko Sep 25, 2026
c61153a
fix(fs): sync an artifact rebuilt in place even when no commit point …
mikolalysenko Sep 25, 2026
0f453ce
fix(fs): harden the group commit's failure and crash-recovery paths
mikolalysenko Sep 25, 2026
40f5e62
test(cli): name the redirect-ledger commit test for what it now asserts
mikolalysenko Sep 25, 2026
e9c86b3
docs(vendor): record the review fixes to the deferral, ledger format …
mikolalysenko Sep 25, 2026
5916139
fix(fs): say why a refused commit journal was set aside
mikolalysenko Sep 25, 2026
6dbbf0e
fix(fs): fsync artifacts at write time on Windows, not at the barrier
mikolalysenko Sep 26, 2026
bfbc088
test(cli): build the failpoints into the optimized test binaries
mikolalysenko Sep 26, 2026
76c90e9
fix(cli): keep patch uuids out of the new debug-assert and debug-log …
mikolalysenko Sep 26, 2026
ed120d8
test: make three new Windows-only failures platform-neutral
mikolalysenko Sep 26, 2026
f9fc676
fix(vendor): stamp rebuilt zips with a Unix host on every platform
mikolalysenko Sep 26, 2026
914f79c
perf(vendor): answer the reuse anchor from the run's shared ledger parse
mikolalysenko Sep 26, 2026
4f07c74
perf(vendor): edit the group-committed ledger in place instead of cop…
mikolalysenko Sep 26, 2026
c493b73
perf(vendor): memoize the pnpm lock split and index its sections
mikolalysenko Sep 26, 2026
7a05a3f
perf(vendor): memoize what the cargo in-sync re-run re-derived per crate
mikolalysenko Sep 26, 2026
c3acf44
perf(crawl): ask the interpreter for its site-packages once per envir…
mikolalysenko Sep 26, 2026
1f59d6d
perf(cargo): parse each workspace manifest once per bytes in the memb…
mikolalysenko Sep 26, 2026
2ef9824
perf(vendor): hold a registry-pin slot for every manifest the residue…
mikolalysenko Sep 26, 2026
bf300ba
fix(crawl): memoize only a successful site-packages query
mikolalysenko Sep 26, 2026
f45f7ee
fix(vendor): keep the ledger captured when an in-place edit unwinds
mikolalysenko Sep 26, 2026
e369bf4
docs(cargo): state what a 512-slot memo costs past its capacity
mikolalysenko Sep 26, 2026
cfeafb0
perf(vendor): index a pnpm lock only once the same lines are probed a…
mikolalysenko Sep 27, 2026
14aa359
perf(hosted): confirm redirects with one multi-needle pass per lock text
mikolalysenko Sep 26, 2026
2731b3d
test(redirect): drop a needless mut from the presence corpus test
mikolalysenko Sep 26, 2026
015f572
perf(redirect): run the independent hosted rewriter groups concurrently
mikolalysenko Sep 26, 2026
651c269
perf(vex): let hosted scan --vex reuse scan's npm crawl for its copy …
mikolalysenko Sep 26, 2026
5938eb7
refactor(api): size each patch-API window from its request count
mikolalysenko Sep 26, 2026
cf4daee
perf(crawl): run the node_modules walk on 4 threads by default
mikolalysenko Sep 26, 2026
7d5e58a
perf(api): raise the authenticated patch-API cap from 8 to 32 in flight
mikolalysenko Sep 26, 2026
19e0e74
perf(crawl): prune CACHEDIR.TAG-tagged directories from the npm roots…
mikolalysenko Sep 26, 2026
d10161c
test(redirect): name the golden-case tuple the group oracle collects
mikolalysenko Sep 26, 2026
bed67ce
test(redirect): pin the python group's cross-rewriter reads in the gr…
mikolalysenko Sep 26, 2026
4dc9719
fix(redirect): run a rewriter group inline when the OS refuses its th…
mikolalysenko Sep 26, 2026
5b70202
test(scan): probe a lone maven suffixed version in the needle equival…
mikolalysenko Sep 26, 2026
d75255c
test(vex): pin the identity fallback answered from the crawl snapshot
mikolalysenko Sep 26, 2026
ceab83d
fix(scan): walk node_modules afresh for hosted VEX after a waiting pr…
mikolalysenko Sep 26, 2026
40ee578
docs: spell out what the CACHEDIR prune, walk pool and API cap reach
mikolalysenko Sep 26, 2026
81f6709
feat(api)!: retry patch-API 429/503 with a bounded, budgeted backoff
mikolalysenko Sep 27, 2026
ab424df
fix(scan)!: report exhausted batch and detail failures in --json warn…
mikolalysenko Sep 27, 2026
943163a
fix(api): bound retries by a wall-clock window; never retry "not conf…
mikolalysenko Sep 27, 2026
5492794
docs: list the patch-API retry as breaking; --json warnings as added
mikolalysenko Sep 27, 2026
2b380e3
Merge origin/main (#256) into perf/scan-concurrency
mikolalysenko Sep 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ crates/socket-patch-core/tests/fixtures/pdm-native/*.lock -text
# refuse CRLF by design (vendor_lockfile_crlf_unsupported), and the tests
# derive their CRLF variants from the LF bytes themselves.
crates/socket-patch-core/tests/fixtures/pnpm-hosted/** -text

# The legacy vendor ledgers are what the base binary wrote, byte for byte:
# vendor_ledger_schema_e2e replays them through `vendor --revert` and
# compares the result byte for byte, so a CRLF checkout would change both
# the replayed wiring files and the expected revert.
crates/socket-patch-cli/tests/fixtures/legacy-ledgers/** -text
282 changes: 280 additions & 2 deletions CHANGELOG.md

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@ sha1 = "=0.10.6"
hex = "=0.4.3"
reqwest = { version = "=0.12.28", features = ["rustls-tls", "json"], default-features = false }
tokio = { version = "=1.50.0", features = ["full"] }
futures-util = { version = "=0.3.32", default-features = false, features = ["std"] }
thiserror = "=2.0.18"
walkdir = "=2.5.0"
uuid = { version = "=1.21.0", features = ["v4"] }
console = "=0.15.11"
dialoguer = "=0.11.0"
tempfile = "=3.26.0"
regex = "=1.12.3"
aho-corasick = "=1.1.4"
glob = "=0.3.4"
toml_edit = "=0.25.12"
once_cell = "=1.21.3"
qbsdiff = "=1.4.4"
rayon = "=1.12.0"
tar = "=0.4.46"
flate2 = "=1.1.9"
zip = { version = "=8.6.0", default-features = false, features = ["deflate"] }
Expand Down
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,40 @@ warning — it never breaks a command or pollutes `--json` output. `socket-patch
cloned repo must never be able to redirect where patches come from or spend your token.
(Full rationale: [docs/design/configuration.md](docs/design/configuration.md).)

One more env-only knob tunes *pacing* rather than routing. `scan` queries the patch API
with several requests in flight: against the authenticated endpoint, a quarter of the
requests a step has to make, between 8 and 32 (so a step with 128 or more requests runs
32 at once, one with 32 or fewer runs 8); against the public proxy, which shares one
server-side limit across anonymous callers, 4. The patch-record fetches behind `vex` and
`scan --vex` run up to 10 at once (4 on the proxy).
`SOCKET_API_CONCURRENCY=<n>` overrides that, clamped to `1`-`32`; on the public proxy it
can only lower it. Set it when an endpoint in front of the API caps in-flight requests
per client — a self-hosted `--api-url`, a corporate reverse proxy, a WAF or a CDN — and
a scan starts reporting fewer patches than it should because some requests are being
rejected. `SOCKET_API_CONCURRENCY=1` sends one request at a time, the slowest and most
conservative setting. An unset, empty or non-numeric value leaves the defaults in place.

A throttled patch API is retried, within bounds. An HTTP `429` or `503` answer to any
patch-API query (batch search, patch lists, patch views, VEX record fetches, hosted
package references) is retried up to 3 times, waiting as long as the server's
`Retry-After` asks (seconds or an HTTP date; a request asked to wait more than 30 s gives
up at once) or, without one, 0.5 s, 1 s, 2 s with jitter. All retries in one run must
finish within 60 s of the run's first retry (wall-clock: requests waiting in parallel
don't add up), so a heavily throttled run gives up instead of hanging. `SOCKET_API_MAX_RETRIES=<n>` changes
the per-request count (`0`-`10`; `0` turns retries off). Other errors are never retried.
A query still throttled after its retries is reported, never dropped: a failed batch
prints `Warning: API batch <n> of <total> failed: …` (under `--json`, a top-level
`warnings[]` entry with code `api_batch_failed`), a failed patch-list lookup prints
`Warning: could not fetch details for <purl>: …` (`--json`: `patch_details_failed`), and
if every query fails the scan exits 1 with an error, as before.

The crawl has a pacing knob too. Its directory walks (`node_modules`, and the Maven
repository with its POM parse) run on a small pool of threads: 4 by default (fewer on a machine with fewer performance cores), because the walk is bound
by the kernel's directory cache and more threads only add system time.
`SOCKET_WALK_THREADS=<n>` overrides that, clamped to `1`-`16` and to the machine's CPU
count; an unset, empty or non-numeric value leaves the default in place. A soft open-file
limit below 128 still runs the walk on one thread, whatever the knob says.

The sections below list only each command's **command-specific** flags.

### `scan`
Expand Down
15 changes: 12 additions & 3 deletions crates/socket-patch-cli/CLI_CONTRACT.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions crates/socket-patch-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ clap = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
futures-util = { workspace = true }
console = { workspace = true }
dialoguer = { workspace = true }
uuid = { workspace = true }
Expand Down Expand Up @@ -62,6 +63,10 @@ docker-e2e = []
setup-e2e = []

[dev-dependencies]
# vendor_crash_safety_e2e / vendor_group_commit_e2e crash the binary through
# its failpoints; with this, `cargo test --release` (the test-release job)
# builds them in too. Dev-only: resolver 2 keeps it out of normal builds.
socket-patch-core = { workspace = true, features = ["failpoints"] }
sha2 = { workspace = true }
# docker_e2e_vendor_maven's host oracle recomputes the maven2 .jar.sha1 sidecar.
sha1 = { workspace = true }
Expand Down
27 changes: 25 additions & 2 deletions crates/socket-patch-cli/src/commands/fetch_stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};

use futures_util::StreamExt;
use socket_patch_core::api::blob_fetcher::{
fetch_missing_blobs, fetch_missing_sources, get_missing_archives, get_missing_blobs,
DownloadMode, FetchMissingBlobsResult,
};
use socket_patch_core::api::client::{get_api_client_with_overrides, ApiClient};
use socket_patch_core::api::client::{get_api_client_with_overrides, hold_back_debug, ApiClient};
use socket_patch_core::manifest::schema::{PatchManifest, PatchRecord};
use socket_patch_core::patch::apply::{is_valid_blob_hash, PatchSources};
use socket_patch_core::utils::concurrent::{api_concurrency_for, ordered_concurrent};
use tempfile::TempDir;

use super::get::base64_decode;
Expand Down Expand Up @@ -565,6 +567,15 @@ pub(crate) async fn stage_vendor_sources_in_memory(
}
};
let mut failed: Vec<&str> = Vec::new();
// The views are fetched concurrently (at most `api_concurrency` in
// flight) but consumed in `to_fetch` order, each request's `--debug`
// lines released at its turn, so `mem`, `failed` and every error
// line fold exactly as the serial loop's did.
let mut views = std::pin::pin!(ordered_concurrent(
to_fetch.iter(),
api_concurrency_for(client.uses_public_proxy(), to_fetch.len()),
|(_, uuid)| async move { (*uuid, hold_back_debug(client.fetch_patch(uuid)).await) },
));
for (i, (purl, uuid)) in to_fetch.iter().enumerate() {
if to_fetch.len() > 1 {
status.set(format!(
Expand All @@ -574,7 +585,19 @@ pub(crate) async fn stage_vendor_sources_in_memory(
to_fetch.len()
));
}
match client.fetch_patch(uuid).await {
let view = match views.next().await {
Some((planned, view)) if planned == *uuid => view.release(),
// Unreachable: the plan IS this list. Falling back to the
// live request keeps the staging COMPLETE if the two ever
// fall out of step — running dry here would otherwise
// return `Ready` with blobs missing and nothing in
// `failed`.
_ => {
debug_assert!(false, "view prefetch plan out of step with the fetch list");
client.fetch_patch(uuid).await
}
};
match view {
Ok(Some(patch)) => {
let mut complete = true;
for (file, info) in &patch.files {
Expand Down
Loading
Loading