Repository navigation
perf(update): resolve in parallel, refresh only changed packages, single recompute - #3055
mikeland73 wants to merge 5 commits into
Conversation
…gle recompute - Resolve packages concurrently in `devbox update` (bounded errgroup), then merge lockfile entries serially in input order. Flakes still warn and continue on failure; versioned packages still abort. - Only pass `--refresh` to `nix build` for packages whose lockfile entry changed. Unchanged packages are built only if missing from the store. - Factor out config-only addToConfig/removeFromConfig so Add replacing a same-canonical-name package and Update migrating legacy packages run ensureStateIsUpToDate once instead of per package. - Remove the post-update `nix flake update` call. Generated flake inputs are locked refs from devbox.lock and flake.lock is deleted whenever flake.nix changes, so it never had anything to update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
[Medium impact] The PR appears safe to merge; the previous findings are fixed and no new actionable issues were found.
|
- RunXRegistry lazily initialized a package-level cache without a lock; parallel resolves in `devbox update` could race on it. Guard it with a mutex. - removeFromConfig now drops the package's lockfile entry. The old Remove path tidied it via ensureStateIsUpToDate; without that, a legacy package re-added under the same name reused its old locked revision. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@greptileai please re-review. Both P1 findings are addressed in 30b254d ("fix(update): guard runx registry init, drop lock entry on config remove"): the runx registry init is now mutex-guarded, and Written by Claude on behalf of / prompted by @mikeland73. |
Deleting the lock entry in removeFromConfig dropped pins that an include still needed. Plain removal now leaves cleanup to lock.File.Tidy again; the entry is forgotten only when a package is removed and re-added under the same name (Add fallback replace, Update legacy migration), which is the case that needs a fresh resolve. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Update's cognitive complexity was 33 (> 32) after the previous changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@greptileai please re-review. All CI checks are green on 3e8b648. The removal-pin finding is addressed in d737261: Written by Claude on behalf of / prompted by @mikeland73. |
Implements Tier 3 items 12, 14, 16 and the first cleanup in item 17 of
specs/perf-improvements.md.Changes
Item 12: parallel resolve in
devbox update.updatePendingPackagesnow resolves packages in a boundederrgroup(8 at a time), then merges lockfile entries serially in input order. Error handling is unchanged: flake refs warn and continue, versioned packages abort.Item 14:
--refreshonly for changed packages.updatePendingPackagesreturns the packages whose lockfile entry actually changed, and only those go intopackagesBeingUpdated.installNixPackagesToStoregroups builds by allow-insecure and refresh, so--refreshapplies only to changed packages. Unchanged packages are built only if they're missing from the store.Item 16: one recompute in
Add/Update. New config-only helpersaddToConfigandremoveFromConfig.Addreplacing a package with the same canonical name no longer callsRemove, which ran its ownensureStateIsUpToDate.Updatemigrating legacy packages no longer callsRemove+Addper package. Each command now runsensureStateIsUpToDateonce at the end.Item 17: remove
nix.FlakeUpdate. It isn't needed:Stdenvand each flake'sResolved).makeFlakeFiledeletesflake.lockwheneverflake.nixchanges.add/installnever ran it.internal/nix/flake_update.gois deleted.Behavior notes
Update, a legacy package migration now savesdevbox.jsononly after the whole update succeeds. Before, it was saved per package, before the lockfile update ran.Testing
go test ./internal/devbox/... ./internal/lock/... ./internal/nix/...passes. The new tests also pass under-race.resolveAndMergePackages: it returns only changed packages, a flake failure warns and continues, a versioned failure aborts, and unversioned packages are skipped.update,update_flake_local,add,add_replace,add_platformsandglobal_addpass locally.update.test.txtnow runs a seconddevbox updateand asserts it reports "Already up-to-date" and installs nothing.🤖 Generated with Claude Code