#include "goal.hh" #include "async-collect.hh" #include "worker.hh" #include namespace nix { bool CompareGoalPtrs::operator() (const GoalPtr & a, const GoalPtr & b) const { std::string s1 = a->key(); std::string s2 = b->key(); return s1 < s2; } void Goal::trace(std::string_view s) { debug("%1%: %2%", name, s); } kj::Promise> Goal::waitForAWhile() try { trace("wait for a while"); /* If we are polling goals that are waiting for a lock, then wake up after a few seconds at most. */ co_await worker.aio.provider->getTimer().afterDelay(settings.pollInterval.get() * kj::SECONDS); co_return ContinueImmediately{}; } catch (...) { co_return std::current_exception(); } kj::Promise> Goal::waitForGoals(kj::Array>> dependencies) noexcept try { auto left = dependencies.size(); for (auto & [dep, p] : dependencies) { p = p.then([this, dep, &left] { left--; trace(fmt("waitee '%s' done; %d left", dep->name, left)); if (dep->exitCode != Goal::ecSuccess) ++nrFailed; if (dep->exitCode == Goal::ecNoSubstituters) ++nrNoSubstituters; if (dep->exitCode == Goal::ecIncompleteClosure) ++nrIncompleteClosure; }).eagerlyEvaluate(nullptr); } auto collectDeps = asyncCollect(std::move(dependencies)); while (auto item = co_await collectDeps.next()) { auto & dep = *item; waiteeDone(dep); if (dep->exitCode == ecFailed && !settings.keepGoing) { co_return result::success(ContinueImmediately{}); } } co_return result::success(ContinueImmediately{}); } catch (...) { co_return result::failure(std::current_exception()); } }