Skip to content

Get rid of addWantedOutputs #13240

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Ericson2314
Copy link
Member

@Ericson2314 Ericson2314 commented May 21, 2025

Motivation

Do this by introducing DerivationTrampolineGoal.

DerivationGoal now only tracks a single output, and is back to tracking a plain store path drvPath, not a deriving path one. Its addWantedOutputs method is gone. These changes will allow subsequent PRs to simplify it greatly.

Because the purpose of each goal is back to being immutable, we can also once again make Goal::buildResult a public field, and get rid of the getBuildResult method. This simplifies things also.

DerivationTrampolineGoal is, as the nane is supposed to indicate, a cheap "trampoline" goal. It takes immutable sets of wanted outputs, and just kicks of DerivationGoals for them. Since now "actual work" is done in these goals, it is not wasteful to have separate ones for separate sets of outputs, even if those outputs (and the derivations they are from) overlap.

This design is described in more detail in the doc comments on the goal types, which I've now greatly expanded.

Context

This separation of concerns will make it possible for future work on issues like #11928, and to continue the path of having more goal types, but each goal type does fewer things (issue #12628).

This commit in some sense reverts f4f28cd, but that one kept around addWantedOutputs. I am quite sure it was having two layers of goals with addWantedOutputs that caused the issues --- restarting logic like addWantedOutputs has is very tempermental! In this version of the change, we have zero layers of addWantedOutputs --- no goal type needs it, or otherwise has a mutable objective --- and so I think this change is safe.


depends on #13186
depends on #13294

Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@github-actions github-actions bot added with-tests Issues related to testing. PRs with tests have some priority fetching Networking with the outside (non-Nix) world, input locking labels May 21, 2025
@Ericson2314 Ericson2314 marked this pull request as ready for review May 21, 2025 00:24
@Ericson2314 Ericson2314 requested a review from edolstra as a code owner May 21, 2025 00:24
@github-project-automation github-project-automation bot moved this to To triage in Nix team May 21, 2025
@Ericson2314 Ericson2314 changed the title Introduce DerivationCreationAndRealisationGoal, get rid of addWantedOutputs Get rid of addWantedOutputs May 21, 2025
Copy link

dpulls bot commented May 21, 2025

🎉 All dependencies have been resolved !

Comment on lines 130 to 135
static bool removeGoal(std::shared_ptr<G> goal, std::weak_ptr<G> & gp)
{
/* !!! inefficient */
cullMap(goalMap, [&](const std::weak_ptr<G> & gp) -> bool {
return gp.lock() != goal;
});
return gp.lock() != goal;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit strange that removeGoal does't actually remove anything now. Maybe something like shouldRemoveGoal is more fitting?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it has to have the same as the others for overloading/recursion reasons.

@Ericson2314 Ericson2314 force-pushed the dyn-drv-take-3 branch 5 times, most recently from a8965c5 to 2ff8cbc Compare May 29, 2025 00:43
@tomberek tomberek requested a review from xokdvium June 4, 2025 20:29
@tomberek tomberek moved this from To triage to 🏁 Review in Nix team Jun 4, 2025
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2025-05-28-nix-team-meeting-minutes-229/65205/1

Copy link

dpulls bot commented Jun 11, 2025

🎉 All dependencies have been resolved !

Comment on lines +86 to +90
try {
drvPath = resolveDerivedPath(worker.store, *drvReq);
} catch (MissingRealisation &) {
return std::nullopt;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big fan of using exceptions as control flow like this. But this is just moving code around, so not a big deal.

Ericson2314 and others added 2 commits June 20, 2025 18:42
This is a minor oversight from 012453d.
This is just a code cleanup; it should not be behavior change.

`addWantedOutputs` is removed by introducing `DerivationTrampolineGoal`.

`DerivationGoal` now only tracks a single output, and is back to
tracking a plain store path `drvPath`, not a deriving path one. Its
`addWantedOutputs` method is gone. These changes will allow subsequent
PRs to simplify it greatly.

Because the purpose of each goal is back to being immutable, we can also
once again make `Goal::buildResult` a public field, and get rid of the
`getBuildResult` method. This simplifies things also.

`DerivationTrampolineGoal` is, as the nane is supposed to indicate, a
cheap "trampoline" goal. It takes immutable sets of wanted outputs, and
just kicks of `DerivationGoal`s for them. Since now "actual work" is
done in these goals, it is not wasteful to have separate ones for
separate sets of outputs, even if those outputs (and the derivations
they are from) overlap.

This design is described in more detail in the doc comments on the goal
types, which I've now greatly expanded.

---

This separation of concerns will make it possible for future work on
issues like NixOS#11928, and to continue the path of having more goal types,
but each goal type does fewer things (issue NixOS#12628).

---

This commit in some sense reverts
f4f28cd, but that one kept around
`addWantedOutputs`. I am quite sure it was having two layers of goals
with `addWantedOutputs` that caused the issues --- restarting logic like
`addWantedOutputs` has is very tempermental! In this version of the
change, we have *zero* layers of `addWantedOutputs` --- no goal type
needs it, or otherwise has a mutable objective --- and so I think this
change is safe.

Co-authored-by: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com>
@Ericson2314
Copy link
Member Author

OK got your last two things, @xokdvium

Copy link
Contributor

@xokdvium xokdvium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High-level design SGTM, but I'm not very familiar with the code yet. This does seem like a good division of responsibilities and is better in terms of SRP.

Left one non-blocking question.

Comment on lines +165 to +172
auto & g = *concreteDrvGoals.begin();
buildResult = g->buildResult;
for (auto & g2 : concreteDrvGoals) {
for (auto && [x, y] : g2->buildResult.builtOutputs)
buildResult.builtOutputs.insert_or_assign(x, y);
}

co_return amDone(g->exitCode, g->ex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking question: what is the semantics of buildResult now? Is the exitCode and ex the same for all concrete goals and only the builtOutputs are now different? I think you've had some low-hanging ideas for a follow-up simplication wrt to this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fetching Networking with the outside (non-Nix) world, input locking with-tests Issues related to testing. PRs with tests have some priority
Projects
Status: 🏁 Review
Development

Successfully merging this pull request may close these issues.

3 participants