libstore: don't use Outcome<void, T> in goals
`Outcome<void, T>` and `Result<std::optional<T>>` can be interpreted as being the same thing, but the latter is easier to use: not only do they allow TRY_AWAIT usage for their promises, we also don't have the error/ exception confusion of outcomes (where the T above is the "error" type) Change-Id: I92c9241481cecc97e2992445b3dced53c82a2524
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include <kj/async.h>
|
||||
#include <kj/debug.h>
|
||||
#include <kj/vector.h>
|
||||
#include <optional>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
@@ -688,13 +689,10 @@ retry:
|
||||
actLock.reset();
|
||||
buildResult.startTime = time(0); // inexact
|
||||
started();
|
||||
auto r = co_await a.promise;
|
||||
if (r.has_value()) {
|
||||
co_return co_await buildDone();
|
||||
} else if (r.has_error()) {
|
||||
co_return r.assume_error();
|
||||
if (auto error = TRY_AWAIT(a.promise)) {
|
||||
co_return *error;
|
||||
} else {
|
||||
co_return r.assume_exception();
|
||||
co_return co_await buildDone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1193,7 +1191,7 @@ Goal::WorkResult DerivationGoal::tooMuchLogs()
|
||||
getName(), settings.maxLogSize));
|
||||
}
|
||||
|
||||
kj::Promise<Outcome<void, Goal::WorkResult>>
|
||||
kj::Promise<Result<std::optional<Goal::WorkResult>>>
|
||||
DerivationGoal::handleBuilderOutput(AsyncInputStream & in) noexcept
|
||||
try {
|
||||
auto buf = kj::heapArray<char>(4096);
|
||||
@@ -1213,7 +1211,7 @@ try {
|
||||
lastChildActivity = AIO().provider.getTimer().now();
|
||||
|
||||
if (data.empty()) {
|
||||
co_return result::success();
|
||||
co_return std::nullopt;
|
||||
}
|
||||
|
||||
logSize += data.size();
|
||||
@@ -1238,8 +1236,8 @@ try {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
kj::Promise<Outcome<void, Goal::WorkResult>> DerivationGoal::handleHookOutput(AsyncInputStream & in
|
||||
) noexcept
|
||||
kj::Promise<Result<std::optional<Goal::WorkResult>>>
|
||||
DerivationGoal::handleHookOutput(AsyncInputStream & in) noexcept
|
||||
try {
|
||||
auto buf = kj::heapArray<char>(4096);
|
||||
while (true) {
|
||||
@@ -1247,7 +1245,7 @@ try {
|
||||
lastChildActivity = AIO().provider.getTimer().now();
|
||||
|
||||
if (data.empty()) {
|
||||
co_return result::success();
|
||||
co_return std::nullopt;
|
||||
}
|
||||
|
||||
for (auto c : data)
|
||||
@@ -1293,7 +1291,7 @@ try {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
kj::Promise<Outcome<void, Goal::WorkResult>> DerivationGoal::handleChildOutput() noexcept
|
||||
kj::Promise<Result<std::optional<Goal::WorkResult>>> DerivationGoal::handleChildOutput() noexcept
|
||||
try {
|
||||
kj::Own<AsyncInputStream> builderIn, hookIn;
|
||||
if (builderOutFD) {
|
||||
@@ -1308,9 +1306,10 @@ try {
|
||||
|
||||
if (respectsTimeouts() && settings.buildTimeout != 0) {
|
||||
handlers = handlers.exclusiveJoin(
|
||||
AIO().provider.getTimer()
|
||||
AIO()
|
||||
.provider.getTimer()
|
||||
.afterDelay(settings.buildTimeout.get() * kj::SECONDS)
|
||||
.then([this]() -> Outcome<void, WorkResult> {
|
||||
.then([this]() -> Result<std::optional<WorkResult>> {
|
||||
return timedOut(
|
||||
Error("%1% timed out after %2% seconds", name, settings.buildTimeout)
|
||||
);
|
||||
@@ -1318,7 +1317,7 @@ try {
|
||||
);
|
||||
}
|
||||
|
||||
return handlers.then([this](auto r) -> Outcome<void, WorkResult> {
|
||||
return handlers.then([this](auto r) {
|
||||
if (!currentLogLine.empty()) flushLine();
|
||||
return r;
|
||||
});
|
||||
@@ -1326,7 +1325,7 @@ try {
|
||||
return {result::current_exception()};
|
||||
}
|
||||
|
||||
kj::Promise<Outcome<void, Goal::WorkResult>> DerivationGoal::monitorForSilence() noexcept
|
||||
kj::Promise<Result<std::optional<Goal::WorkResult>>> DerivationGoal::monitorForSilence() noexcept
|
||||
{
|
||||
while (true) {
|
||||
const auto stash = lastChildActivity;
|
||||
@@ -1340,7 +1339,7 @@ kj::Promise<Outcome<void, Goal::WorkResult>> DerivationGoal::monitorForSilence()
|
||||
}
|
||||
}
|
||||
|
||||
kj::Promise<Outcome<void, Goal::WorkResult>>
|
||||
kj::Promise<Result<std::optional<Goal::WorkResult>>>
|
||||
DerivationGoal::handleChildStreams(AsyncInputStream * builderIn, AsyncInputStream * hookIn) noexcept
|
||||
{
|
||||
assert(builderIn || hookIn);
|
||||
@@ -1348,7 +1347,7 @@ DerivationGoal::handleChildStreams(AsyncInputStream * builderIn, AsyncInputStrea
|
||||
lastChildActivity = AIO().provider.getTimer().now();
|
||||
|
||||
auto handlers = kj::joinPromisesFailFast([&] {
|
||||
kj::Vector<kj::Promise<Outcome<void, WorkResult>>> parts{2};
|
||||
kj::Vector<kj::Promise<Result<std::optional<WorkResult>>>> parts{2};
|
||||
|
||||
if (builderIn) {
|
||||
parts.add(handleBuilderOutput(*builderIn));
|
||||
@@ -1367,9 +1366,11 @@ DerivationGoal::handleChildStreams(AsyncInputStream * builderIn, AsyncInputStrea
|
||||
}
|
||||
|
||||
for (auto r : co_await handlers) {
|
||||
BOOST_OUTCOME_CO_TRYV(r);
|
||||
if (r) {
|
||||
co_return r;
|
||||
}
|
||||
}
|
||||
co_return result::success();
|
||||
co_return std::nullopt;
|
||||
}
|
||||
|
||||
void DerivationGoal::flushLine()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lix/libstore/pathlocks.hh"
|
||||
#include "lix/libstore/build/goal.hh"
|
||||
#include <kj/time.h>
|
||||
#include <optional>
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -18,7 +19,7 @@ struct HookInstance;
|
||||
|
||||
struct HookReplyBase {
|
||||
struct [[nodiscard]] Accept {
|
||||
kj::Promise<Outcome<void, Goal::WorkResult>> promise;
|
||||
kj::Promise<Result<std::optional<Goal::WorkResult>>> promise;
|
||||
};
|
||||
struct [[nodiscard]] Decline {};
|
||||
struct [[nodiscard]] Postpone {};
|
||||
@@ -313,12 +314,13 @@ struct DerivationGoal : public Goal
|
||||
protected:
|
||||
kj::TimePoint lastChildActivity = kj::minValue;
|
||||
|
||||
kj::Promise<Outcome<void, WorkResult>> handleChildOutput() noexcept;
|
||||
kj::Promise<Outcome<void, WorkResult>>
|
||||
kj::Promise<Result<std::optional<WorkResult>>> handleChildOutput() noexcept;
|
||||
kj::Promise<Result<std::optional<WorkResult>>>
|
||||
handleChildStreams(AsyncInputStream * builderIn, AsyncInputStream * hookIn) noexcept;
|
||||
kj::Promise<Outcome<void, WorkResult>> handleBuilderOutput(AsyncInputStream & in) noexcept;
|
||||
kj::Promise<Outcome<void, WorkResult>> handleHookOutput(AsyncInputStream & in) noexcept;
|
||||
kj::Promise<Outcome<void, WorkResult>> monitorForSilence() noexcept;
|
||||
kj::Promise<Result<std::optional<WorkResult>>> handleBuilderOutput(AsyncInputStream & in
|
||||
) noexcept;
|
||||
kj::Promise<Result<std::optional<WorkResult>>> handleHookOutput(AsyncInputStream & in) noexcept;
|
||||
kj::Promise<Result<std::optional<WorkResult>>> monitorForSilence() noexcept;
|
||||
WorkResult tooMuchLogs();
|
||||
void flushLine();
|
||||
|
||||
|
||||
@@ -261,13 +261,8 @@ retry:
|
||||
TRY_AWAIT(startBuilder());
|
||||
|
||||
started();
|
||||
auto r = co_await handleChildOutput();
|
||||
if (r.has_value()) {
|
||||
// all good so far
|
||||
} else if (r.has_error()) {
|
||||
co_return r.assume_error();
|
||||
} else {
|
||||
co_return r.assume_exception();
|
||||
if (auto error = TRY_AWAIT(handleChildOutput())) {
|
||||
co_return std::move(*error);
|
||||
}
|
||||
|
||||
} catch (BuildError & e) {
|
||||
|
||||
Reference in New Issue
Block a user