From d5db0b1abc1809ad97fa28b82056b19c4a45710a Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Mon, 30 Sep 2024 01:31:30 +0200 Subject: [PATCH] libstore: turn periodic gc attempt into a promise notably we will check whether we want to do GC at all only once during startup, and we'll only attempt GC every ten seconds rather than every time a goal has finished a partial work call. this shouldn't cause any problems in practice since relying on auto-gc is not deterministic and stores in which builds can fill all remaining free space in merely ten seconds are severely troubled even when gargage collection runs a lot. Change-Id: I1175a56bf7f4e531f8be90157ad88750ff2ddec4 --- src/libstore/build/worker.cc | 36 ++++++++++++++++++++---------------- src/libstore/build/worker.hh | 2 ++ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index 8ab7fcc86..e9904a1f5 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -298,6 +298,13 @@ std::vector Worker::run(std::function req) } auto promise = runImpl(); + + // TODO GC interface? + if (auto localStore = dynamic_cast(&store); localStore && settings.minFree != 0) { + // Periodically wake up to see if we need to run the garbage collector. + promise = promise.exclusiveJoin(boopGC(*localStore)); + } + promise.wait(aio.waitScope).value(); std::vector results; @@ -315,10 +322,6 @@ try { checkInterrupt(); - // TODO GC interface? - if (auto localStore = dynamic_cast(&store)) - localStore->autoGC(false); - /* Call every wake goal (in the ordering established by CompareGoalPtrs). */ while (!awake.empty() && !topGoals.empty()) { @@ -356,22 +359,23 @@ try { co_return result::failure(std::current_exception()); } +kj::Promise> Worker::boopGC(LocalStore & localStore) +try { + while (true) { + co_await aio.provider->getTimer().afterDelay(10 * kj::SECONDS); + localStore.autoGC(false); + } +} catch (...) { + co_return result::failure(std::current_exception()); +} + kj::Promise> Worker::waitForInput() try { printMsg(lvlVomit, "waiting for children"); - auto waitFor = [&]{ - auto pair = kj::newPromiseAndFulfiller(); - this->childFinished = kj::mv(pair.fulfiller); - return kj::mv(pair.promise); - }(); - - if (settings.minFree.get() != 0) { - // Periodicallty wake up to see if we need to run the garbage collector. - waitFor = waitFor.exclusiveJoin(aio.provider->getTimer().afterDelay(10 * kj::SECONDS)); - } - - co_await waitFor; + auto pair = kj::newPromiseAndFulfiller(); + this->childFinished = kj::mv(pair.fulfiller); + co_await pair.promise; co_return result::success(); } catch (...) { co_return result::failure(std::current_exception()); diff --git a/src/libstore/build/worker.hh b/src/libstore/build/worker.hh index 6da76fe34..dc85c43e3 100644 --- a/src/libstore/build/worker.hh +++ b/src/libstore/build/worker.hh @@ -20,6 +20,7 @@ namespace nix { struct DerivationGoal; struct PathSubstitutionGoal; class DrvOutputSubstitutionGoal; +class LocalStore; typedef std::chrono::time_point steady_time_point; @@ -189,6 +190,7 @@ private: } kj::Promise> runImpl(); + kj::Promise> boopGC(LocalStore & localStore); public: