async: open the floodgates.

this will let us add AsyncIoRoots to the toplevel objects and functions.
eventually we'll get rid of all offloading again byt covering the entire
space between main() and the worker entry points with promises. it won't
be a quick and easy journey; we have somewhere around 200 functions that
must be converted to async code, and some building blocks that are fully
incompatible with event loops on their own. this ranges from simple bits
like thread pools (which we can wrap in promise-fulfiller pairs), bigger
bits like the curl wrapper (which we can make async, but not easily), or
even impossible bits (like the libarchive wrapper, which can't be turned
into async code at all. not to worry though, we have *plans* for those.)

Change-Id: I95b91b0545659ece4ec1b85214df1ce2f1bc0164
This commit is contained in:
eldritch horrors
2025-01-24 13:48:44 +00:00
parent b03195ab00
commit 0275b9a92f
+13 -27
View File
@@ -2,21 +2,19 @@
#include "lix/libstore/build/substitution-goal.hh"
#include "lix/libstore/build/derivation-goal.hh"
#include "lix/libstore/local-store.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/strings.hh"
namespace nix {
void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode, std::shared_ptr<Store> evalStore)
{
auto kjaio = kj::setupAsyncIo();
AsyncContext aio(kjaio);
auto results = processGoals(*this, evalStore ? *evalStore : *this, [&](GoalFactory & gf) {
auto results = RUN_ASYNC_IN_NEW_THREAD(processGoals(*this, evalStore ? *evalStore : *this, [&](GoalFactory & gf) {
Worker::Targets goals;
for (auto & br : reqs)
goals.emplace_back(gf.makeGoal(br, buildMode));
return goals;
}).wait(kjaio.waitScope).value();
}));
StringSet failed;
std::shared_ptr<Error> ex;
@@ -47,16 +45,13 @@ std::vector<KeyedBuildResult> Store::buildPathsWithResults(
BuildMode buildMode,
std::shared_ptr<Store> evalStore)
{
auto kjaio = kj::setupAsyncIo();
AsyncContext aio(kjaio);
auto goals = processGoals(*this, evalStore ? *evalStore : *this, [&](GoalFactory & gf) {
auto goals = RUN_ASYNC_IN_NEW_THREAD(processGoals(*this, evalStore ? *evalStore : *this, [&](GoalFactory & gf) {
Worker::Targets goals;
for (const auto & req : reqs) {
goals.emplace_back(gf.makeGoal(req, buildMode));
}
return goals;
}).wait(kjaio.waitScope).value().goals;
})).goals;
std::vector<KeyedBuildResult> results;
@@ -69,15 +64,12 @@ std::vector<KeyedBuildResult> Store::buildPathsWithResults(
BuildResult Store::buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
BuildMode buildMode)
{
auto kjaio = kj::setupAsyncIo();
AsyncContext aio(kjaio);
try {
auto results = processGoals(*this, *this, [&](GoalFactory & gf) {
auto results = RUN_ASYNC_IN_NEW_THREAD(processGoals(*this, *this, [&](GoalFactory & gf) {
Worker::Targets goals;
goals.emplace_back(gf.makeBasicDerivationGoal(drvPath, drv, OutputsSpec::All{}, buildMode));
return goals;
}).wait(kjaio.waitScope).value();
}));
auto & result = results.goals.begin()->second;
return result.result.restrictTo(DerivedPath::Built {
.drvPath = makeConstantStorePathRef(drvPath),
@@ -97,14 +89,11 @@ void Store::ensurePath(const StorePath & path)
/* If the path is already valid, we're done. */
if (isValidPath(path)) return;
auto kjaio = kj::setupAsyncIo();
AsyncContext aio(kjaio);
auto results = processGoals(*this, *this, [&](GoalFactory & gf) {
auto results = RUN_ASYNC_IN_NEW_THREAD(processGoals(*this, *this, [&](GoalFactory & gf) {
Worker::Targets goals;
goals.emplace_back(gf.makePathSubstitutionGoal(path));
return goals;
}).wait(kjaio.waitScope).value();
}));
auto & result = results.goals.begin()->second;
if (result.exitCode != Goal::ecSuccess) {
@@ -119,14 +108,11 @@ void Store::ensurePath(const StorePath & path)
void Store::repairPath(const StorePath & path)
{
auto kjaio = kj::setupAsyncIo();
AsyncContext aio(kjaio);
auto results = processGoals(*this, *this, [&](GoalFactory & gf) {
auto results = RUN_ASYNC_IN_NEW_THREAD(processGoals(*this, *this, [&](GoalFactory & gf) {
Worker::Targets goals;
goals.emplace_back(gf.makePathSubstitutionGoal(path, Repair));
return goals;
}).wait(kjaio.waitScope).value();
}));
auto & result = results.goals.begin()->second;
if (result.exitCode != Goal::ecSuccess) {
@@ -134,7 +120,7 @@ void Store::repairPath(const StorePath & path)
deriver, then rebuild the deriver. */
auto info = queryPathInfo(path);
if (info->deriver && isValidPath(*info->deriver)) {
processGoals(*this, *this, [&](GoalFactory & gf) {
RUN_ASYNC_IN_NEW_THREAD(processGoals(*this, *this, [&](GoalFactory & gf) {
Worker::Targets goals;
goals.emplace_back(gf.makeGoal(
DerivedPath::Built{
@@ -145,7 +131,7 @@ void Store::repairPath(const StorePath & path)
bmRepair
));
return goals;
}).wait(kjaio.waitScope).value();
}));
} else
throw Error(results.failingExitStatus, "cannot repair path '%s'", printStorePath(path));
}