Nix 2.93.3
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;
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 std::optional<Path> buildDirOverride;
199
200private:
201 kj::TaskSet children;
202
203public:
204 struct HookState {
205 std::unique_ptr<HookInstance> instance;
206
211 bool available = true;
212 };
213
214 HookState hook;
215
216 NotifyingCounter<uint64_t> expectedBuilds{[this] { updateStatisticsLater(); }};
217 NotifyingCounter<uint64_t> doneBuilds{[this] { updateStatisticsLater(); }};
218 NotifyingCounter<uint64_t> failedBuilds{[this] { updateStatisticsLater(); }};
219 NotifyingCounter<uint64_t> runningBuilds{[this] { updateStatisticsLater(); }};
220
221 NotifyingCounter<uint64_t> expectedSubstitutions{[this] { updateStatisticsLater(); }};
222 NotifyingCounter<uint64_t> doneSubstitutions{[this] { updateStatisticsLater(); }};
223 NotifyingCounter<uint64_t> failedSubstitutions{[this] { updateStatisticsLater(); }};
224 NotifyingCounter<uint64_t> runningSubstitutions{[this] { updateStatisticsLater(); }};
225 NotifyingCounter<uint64_t> expectedDownloadSize{[this] { updateStatisticsLater(); }};
226 NotifyingCounter<uint64_t> doneDownloadSize{[this] { updateStatisticsLater(); }};
227 NotifyingCounter<uint64_t> expectedNarSize{[this] { updateStatisticsLater(); }};
228 NotifyingCounter<uint64_t> doneNarSize{[this] { updateStatisticsLater(); }};
229
230private:
231 Worker(Store & store, Store & evalStore);
232 ~Worker();
233
237
241 template<typename ID, std::derived_from<Goal> G>
242 std::pair<std::shared_ptr<G>, kj::Promise<Result<Goal::WorkResult>>> makeGoalCommon(
243 std::map<ID, CachedGoal<G>> & map,
244 const ID & key,
245 InvocableR<std::unique_ptr<G>> auto create,
246 InvocableR<bool, G &> auto modify
247 );
248 std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<Result<Goal::WorkResult>>> makeDerivationGoal(
249 const StorePath & drvPath,
250 const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal) override;
251 kj::Promise<
252 Result<std::pair<std::shared_ptr<DerivationGoal>, kj::Promise<Result<Goal::WorkResult>>>>>
253 makeBasicDerivationGoal(
254 const StorePath & drvPath,
255 const BasicDerivation & drv,
256 const OutputsSpec & wantedOutputs,
257 BuildMode buildMode = bmNormal
258 ) override;
259
263 std::pair<std::shared_ptr<PathSubstitutionGoal>, kj::Promise<Result<Goal::WorkResult>>>
264 makePathSubstitutionGoal(
265 const StorePath & storePath,
266 RepairFlag repair = NoRepair,
267 std::optional<ContentAddress> ca = std::nullopt
268 ) override;
269 std::pair<std::shared_ptr<DrvOutputSubstitutionGoal>, kj::Promise<Result<Goal::WorkResult>>>
270 makeDrvOutputSubstitutionGoal(
271 const DrvOutput & id,
272 RepairFlag repair = NoRepair,
273 std::optional<ContentAddress> ca = std::nullopt
274 ) override;
275
282 std::pair<GoalPtr, kj::Promise<Result<Goal::WorkResult>>>
283 makeGoal(const DerivedPath & req, BuildMode buildMode = bmNormal) override;
284
285 kj::Promise<Result<Results>> run(Targets topGoals);
286
287public:
291 kj::Promise<Result<Results>> run(std::function<kj::Promise<Result<Targets>>(GoalFactory &)> req)
292 try {
293 co_return co_await run(TRY_AWAIT(req(goalFactory())));
294 } catch (...) {
295 co_return result::current_exception();
296 }
297
298 kj::Promise<Result<Results>> run(std::function<Targets(GoalFactory &)> req)
299 try {
300 return run(req(goalFactory()));
301 } catch (...) {
302 return {result::current_exception()};
303 }
304
309 kj::Promise<Result<bool>> pathContentsGood(const StorePath & path);
310
311 void markContentsGood(const StorePath & path);
312
313 template<typename MkGoals>
314 friend kj::Promise<Result<Results>>
315 processGoals(Store & store, Store & evalStore, MkGoals && mkGoals) noexcept;
316};
317
318template<typename MkGoals>
319kj::Promise<Result<Worker::Results>>
320processGoals(Store & store, Store & evalStore, MkGoals && mkGoals) noexcept
321try {
322 co_return co_await Worker(store, evalStore).run(std::forward<MkGoals>(mkGoals));
323} catch (...) {
324 co_return result::current_exception();
325}
326}
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 local-store.hh:78
Definition notifying-counter.hh:12
Definition path.hh:21
Definition store-api.hh:195
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:291
Definition derivations.hh:274
Definition derivation-goal.hh:73
Definition derived-path.hh:225
Definition realisation.hh:24
Definition hook-instance.hh:11
Definition outputs-spec.hh:28
Definition substitution-goal.hh:14
Definition worker.hh:204
bool available
Definition worker.hh:211
Definition worker.hh:92
unsigned int failingExitStatus
Definition worker.hh:123
std::map< size_t, Goal::WorkResult > goals
Definition worker.hh:100