Nix  2.93.0-dev
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
worker.hh
Go to the documentation of this file.
1#pragma once
3
6#include "lix/libutil/concepts.hh"
10#include "lix/libstore/lock.hh"
14
15#include <future>
16#include <kj/async-io.h>
17#include <thread>
18
19namespace nix {
20
21/* Forward definition. */
22struct DerivationGoal;
23struct PathSubstitutionGoal;
24class DrvOutputSubstitutionGoal;
25class LocalStore;
26
27typedef std::chrono::time_point<std::chrono::steady_clock> steady_time_point;
28
29/* Forward definition. */
30struct HookInstance;
31
33{
34public:
35 virtual std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<Result<Goal::WorkResult>>>
36 makeDerivationGoal(
37 const StorePath & drvPath, const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal
38 ) = 0;
39 virtual kj::Promise<
40 Result<std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<Result<Goal::WorkResult>>>>>
41 makeBasicDerivationGoal(
42 const StorePath & drvPath,
43 const BasicDerivation & drv,
44 const OutputsSpec & wantedOutputs,
45 BuildMode buildMode = bmNormal
46 ) = 0;
47
51 virtual std::pair<std::shared_ptr<PathSubstitutionGoal>, kj::Promise<Result<Goal::WorkResult>>>
53 const StorePath & storePath,
54 RepairFlag repair = NoRepair,
55 std::optional<ContentAddress> ca = std::nullopt
56 ) = 0;
57 virtual std::pair<std::shared_ptr<DrvOutputSubstitutionGoal>, kj::Promise<Result<Goal::WorkResult>>>
58 makeDrvOutputSubstitutionGoal(
59 const DrvOutput & id,
60 RepairFlag repair = NoRepair,
61 std::optional<ContentAddress> ca = std::nullopt
62 ) = 0;
63
70 virtual std::pair<GoalPtr, kj::Promise<Result<Goal::WorkResult>>>
71 makeGoal(const DerivedPath & req, BuildMode buildMode = bmNormal) = 0;
72};
73
74// elaborate hoax to let goals access factory methods while hiding them from the public
75class WorkerBase : protected GoalFactory
76{
77 friend struct DerivationGoal;
78 friend struct PathSubstitutionGoal;
79 friend class DrvOutputSubstitutionGoal;
80
81protected:
82 GoalFactory & goalFactory() { return *this; }
83};
84
88class Worker : public WorkerBase
89{
90public:
91 using Targets = std::vector<std::pair<GoalPtr, kj::Promise<Result<Goal::WorkResult>>>>;
92 struct Results {
100 std::map<size_t, Goal::WorkResult> goals;
101
123 unsigned int failingExitStatus;
124 };
125
126private:
127
128 bool running = false;
129
130 template<typename G>
131 struct CachedGoal
132 {
133 std::shared_ptr<G> goal;
134 kj::ForkedPromise<Result<Goal::WorkResult>> promise{nullptr};
135 };
140 std::map<StorePath, CachedGoal<DerivationGoal>> derivationGoals;
141 std::map<StorePath, CachedGoal<PathSubstitutionGoal>> substitutionGoals;
142 std::map<DrvOutput, CachedGoal<DrvOutputSubstitutionGoal>> drvOutputSubstitutionGoals;
143
147 std::map<StorePath, bool> pathContentsGoodCache;
148
153 bool permanentFailure = false;
154
158 bool timedOut = false;
159
163 bool hashMismatch = false;
164
168 bool checkMismatch = false;
169
173 kj::Promise<Result<Results>> updateStatistics();
174
175 AsyncSemaphore statisticsUpdateSignal{1};
176 std::optional<AsyncSemaphore::Token> statisticsUpdateInhibitor;
177
181 void updateStatisticsLater()
182 {
183 statisticsUpdateInhibitor = {};
184 }
185
186 kj::Promise<Result<Results>> runImpl(Targets topGoals);
187 kj::Promise<Result<Results>> boopGC(LocalStore & localStore);
188
189public:
190
191 const Activity act;
192 const Activity actDerivations;
193 const Activity actSubstitutions;
194
195 Store & store;
196 Store & evalStore;
197 AsyncSemaphore substitutions, localBuilds;
198
199private:
200 kj::TaskSet children;
201
202public:
203 struct HookState {
204 std::unique_ptr<HookInstance> instance;
205
210 bool available = true;
211 };
212
213 HookState hook;
214
215 NotifyingCounter<uint64_t> expectedBuilds{[this] { updateStatisticsLater(); }};
216 NotifyingCounter<uint64_t> doneBuilds{[this] { updateStatisticsLater(); }};
217 NotifyingCounter<uint64_t> failedBuilds{[this] { updateStatisticsLater(); }};
218 NotifyingCounter<uint64_t> runningBuilds{[this] { updateStatisticsLater(); }};
219
220 NotifyingCounter<uint64_t> expectedSubstitutions{[this] { updateStatisticsLater(); }};
221 NotifyingCounter<uint64_t> doneSubstitutions{[this] { updateStatisticsLater(); }};
222 NotifyingCounter<uint64_t> failedSubstitutions{[this] { updateStatisticsLater(); }};
223 NotifyingCounter<uint64_t> runningSubstitutions{[this] { updateStatisticsLater(); }};
224 NotifyingCounter<uint64_t> expectedDownloadSize{[this] { updateStatisticsLater(); }};
225 NotifyingCounter<uint64_t> doneDownloadSize{[this] { updateStatisticsLater(); }};
226 NotifyingCounter<uint64_t> expectedNarSize{[this] { updateStatisticsLater(); }};
227 NotifyingCounter<uint64_t> doneNarSize{[this] { updateStatisticsLater(); }};
228
229private:
230 Worker(Store & store, Store & evalStore);
231 ~Worker();
232
240 template<typename ID, std::derived_from<Goal> G>
241 std::pair<std::shared_ptr<G>, kj::Promise<Result<Goal::WorkResult>>> makeGoalCommon(
242 std::map<ID, CachedGoal<G>> & map,
243 const ID & key,
244 InvocableR<std::unique_ptr<G>> auto create,
245 InvocableR<bool, G &> auto modify
246 );
247 std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<Result<Goal::WorkResult>>> makeDerivationGoal(
248 const StorePath & drvPath,
249 const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal) override;
250 kj::Promise<
251 Result<std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<Result<Goal::WorkResult>>>>>
252 makeBasicDerivationGoal(
253 const StorePath & drvPath,
254 const BasicDerivation & drv,
255 const OutputsSpec & wantedOutputs,
256 BuildMode buildMode = bmNormal
257 ) override;
258
262 std::pair<std::shared_ptr<PathSubstitutionGoal>, kj::Promise<Result<Goal::WorkResult>>>
263 makePathSubstitutionGoal(
264 const StorePath & storePath,
265 RepairFlag repair = NoRepair,
266 std::optional<ContentAddress> ca = std::nullopt
267 ) override;
268 std::pair<std::shared_ptr<DrvOutputSubstitutionGoal>, kj::Promise<Result<Goal::WorkResult>>>
269 makeDrvOutputSubstitutionGoal(
270 const DrvOutput & id,
271 RepairFlag repair = NoRepair,
272 std::optional<ContentAddress> ca = std::nullopt
273 ) override;
274
281 std::pair<GoalPtr, kj::Promise<Result<Goal::WorkResult>>>
282 makeGoal(const DerivedPath & req, BuildMode buildMode = bmNormal) override;
283
284 kj::Promise<Result<Results>> run(Targets topGoals);
285
286public:
290 kj::Promise<Result<Results>> run(std::function<kj::Promise<Result<Targets>>(GoalFactory &)> req)
291 try {
292 co_return co_await run(TRY_AWAIT(req(goalFactory())));
293 } catch (...) {
294 co_return result::current_exception();
295 }
296
297 kj::Promise<Result<Results>> run(std::function<Targets(GoalFactory &)> req)
298 try {
299 return run(req(goalFactory()));
300 } catch (...) {
301 return {result::current_exception()};
302 }
303
308 kj::Promise<Result<bool>> pathContentsGood(const StorePath & path);
309
310 void markContentsGood(const StorePath & path);
311
312 template<typename MkGoals>
313 friend kj::Promise<Result<Results>>
314 processGoals(Store & store, Store & evalStore, MkGoals && mkGoals) noexcept;
315};
316
317template<typename MkGoals>
318kj::Promise<Result<Worker::Results>>
319processGoals(Store & store, Store & evalStore, MkGoals && mkGoals) noexcept
320try {
321 co_return co_await Worker(store, evalStore).run(std::forward<MkGoals>(mkGoals));
322} catch (...) {
323 co_return result::current_exception();
324}
325}
A semaphore implementation usable from within a KJ event loop.
Definition drv-output-substitution-goal.hh:21
Definition worker.hh:33
virtual std::pair< std::shared_ptr< PathSubstitutionGoal >, kj::Promise< Result< Goal::WorkResult > > > makePathSubstitutionGoal(const StorePath &storePath, RepairFlag repair=NoRepair, std::optional< ContentAddress > ca=std::nullopt)=0
virtual std::pair< GoalPtr, kj::Promise< Result< Goal::WorkResult > > > makeGoal(const DerivedPath &req, BuildMode buildMode=bmNormal)=0
Definition notifying-counter.hh:12
Definition path.hh:21
Definition worker.hh:76
Definition worker.hh:89
kj::Promise< Result< bool > > pathContentsGood(const StorePath &path)
Definition worker.cc:325
kj::Promise< Result< Results > > run(std::function< kj::Promise< Result< Targets > >(GoalFactory &)> req)
Definition worker.hh:290
Definition derivations.hh:274
Definition derivation-goal.hh:73
Definition derived-path.hh:225
Definition realisation.hh:24
Definition outputs-spec.hh:28
Definition substitution-goal.hh:14
Definition worker.hh:203
bool available
Definition worker.hh:210
Definition worker.hh:92
unsigned int failingExitStatus
Definition worker.hh:123
std::map< size_t, Goal::WorkResult > goals
Definition worker.hh:100