diff options
-rw-r--r-- | third_party/nix/src/libstore/rpc-store.cc | 51 | ||||
-rw-r--r-- | third_party/nix/src/libstore/store-api.cc | 4 | ||||
-rw-r--r-- | third_party/nix/src/libstore/store-api.hh | 4 | ||||
-rw-r--r-- | third_party/nix/src/nix-daemon/nix-daemon-proto.cc | 23 | ||||
-rw-r--r-- | third_party/nix/src/proto/worker.proto | 35 |
5 files changed, 92 insertions, 25 deletions
diff --git a/third_party/nix/src/libstore/rpc-store.cc b/third_party/nix/src/libstore/rpc-store.cc index 2d1278f40c78..f3fc5582f3ef 100644 --- a/third_party/nix/src/libstore/rpc-store.cc +++ b/third_party/nix/src/libstore/rpc-store.cc @@ -3,6 +3,7 @@ #include <algorithm> #include <filesystem> #include <memory> +#include <optional> #include <absl/status/status.h> #include <absl/strings/str_cat.h> @@ -326,8 +327,32 @@ absl::Status RpcStore::buildPaths(const PathSet& paths, BuildMode buildMode) { google::protobuf::Empty response; request.set_mode(nix::BuildModeToProto(buildMode)); - return nix::util::proto::GRPCStatusToAbsl( - stub_->BuildPaths(&ctx, request, &response)); + + // TODO(tazjin): Temporary no-op sink used to discard build output, + // but satisfy the compiler. A real one is needed. + // + // Maybe this should just be stderr, considering that this is the + // *client*, but I'm not sure. + std::ostream discard_logs = DiscardLogsSink(); + + std::unique_ptr<grpc::ClientReader<proto::BuildEvent>> reader = + stub_->BuildPaths(&ctx, request); + + proto::BuildEvent event; + while (reader->Read(&event)) { + if (event.has_build_log()) { + // TODO(tazjin): Include .path()? + discard_logs << event.build_log().line(); + } else { + discard_logs << std::endl + << "Building path: " << event.building_path().path() + << std::endl; + } + + // has_result() is not in use in this call (for now) + } + + return nix::util::proto::GRPCStatusToAbsl(reader->Finish()); } BuildResult RpcStore::buildDerivation(const Path& drvPath, @@ -339,11 +364,25 @@ BuildResult RpcStore::buildDerivation(const Path& drvPath, auto proto_drv = drv.to_proto(); request.set_allocated_derivation(&proto_drv); request.set_build_mode(BuildModeToProto(buildMode)); - proto::BuildDerivationResponse response; - SuccessOrThrow(stub_->BuildDerivation(&ctx, request, &response), - __FUNCTION__); - const auto result = BuildResult::FromProto(response); + // Same note as in ::buildPaths ... + std::ostream discard_logs = DiscardLogsSink(); + + std::unique_ptr<grpc::ClientReader<proto::BuildEvent>> reader = + stub_->BuildDerivation(&ctx, request); + + std::optional<BuildResult> result; + + proto::BuildEvent event; + while (reader->Read(&event)) { + if (event.has_build_log()) { + discard_logs << event.build_log().line(); + } else if (event.has_result()) { + result = BuildResult::FromProto(event.result()); + } + } + SuccessOrThrow(reader->Finish(), __FUNCTION__); + if (!result.has_value()) { throw Error("Invalid response from daemon for buildDerivation"); } diff --git a/third_party/nix/src/libstore/store-api.cc b/third_party/nix/src/libstore/store-api.cc index 3ada63532ca2..7972f5083657 100644 --- a/third_party/nix/src/libstore/store-api.cc +++ b/third_party/nix/src/libstore/store-api.cc @@ -92,7 +92,7 @@ nix::proto::BuildStatus BuildResult::status_to_proto() { } std::optional<BuildResult> BuildResult::FromProto( - const nix::proto::BuildDerivationResponse& resp) { + const nix::proto::BuildResult& resp) { BuildResult result; switch (resp.status()) { case proto::BuildStatus::Built: @@ -125,7 +125,7 @@ std::optional<BuildResult> BuildResult::FromProto( return {}; } - result.errorMsg = resp.error_message(); + result.errorMsg = resp.msg(); return result; } diff --git a/third_party/nix/src/libstore/store-api.hh b/third_party/nix/src/libstore/store-api.hh index 39769dfb3cd0..1d81b228f292 100644 --- a/third_party/nix/src/libstore/store-api.hh +++ b/third_party/nix/src/libstore/store-api.hh @@ -189,7 +189,7 @@ struct ValidPathInfo { virtual ~ValidPathInfo() {} }; -typedef std::list<ValidPathInfo> ValidPathInfos; +using ValidPathInfos = std::list<ValidPathInfo>; enum BuildMode { bmNormal, bmRepair, bmCheck }; @@ -243,7 +243,7 @@ struct BuildResult { nix::proto::BuildStatus status_to_proto(); static std::optional<BuildResult> FromProto( - const nix::proto::BuildDerivationResponse& resp); + const nix::proto::BuildResult& resp); }; class Store : public std::enable_shared_from_this<Store>, public Config { diff --git a/third_party/nix/src/nix-daemon/nix-daemon-proto.cc b/third_party/nix/src/nix-daemon/nix-daemon-proto.cc index ec8e0ff42cc3..b7d5836091af 100644 --- a/third_party/nix/src/nix-daemon/nix-daemon-proto.cc +++ b/third_party/nix/src/nix-daemon/nix-daemon-proto.cc @@ -29,7 +29,6 @@ namespace nix::daemon { using ::google::protobuf::util::TimeUtil; using ::grpc::Status; -using ::nix::proto::BuildStatus; using ::nix::proto::PathInfo; using ::nix::proto::StorePath; using ::nix::proto::StorePaths; @@ -271,9 +270,9 @@ class WorkerServiceImpl final : public WorkerService::Service { __FUNCTION__); } - Status BuildPaths(grpc::ServerContext*, - const nix::proto::BuildPathsRequest* request, - google::protobuf::Empty*) override { + Status BuildPaths( + grpc::ServerContext*, const nix::proto::BuildPathsRequest* request, + grpc::ServerWriter<nix::proto::BuildEvent>* /* writer */) override { return HandleExceptions( [&]() -> Status { PathSet drvs; @@ -612,7 +611,7 @@ class WorkerServiceImpl final : public WorkerService::Service { Status BuildDerivation( grpc::ServerContext* context, const nix::proto::BuildDerivationRequest* request, - nix::proto::BuildDerivationResponse* response) override { + grpc::ServerWriter<nix::proto::BuildEvent>* writer) override { return HandleExceptions( [&]() -> Status { auto drv_path = request->drv_path().path(); @@ -625,11 +624,19 @@ class WorkerServiceImpl final : public WorkerService::Service { return Status(grpc::StatusCode::INTERNAL, "Invalid build mode"); } - auto res = store_->buildDerivation(drv_path, drv, *build_mode); + BuildResult res = store_->buildDerivation(drv_path, drv, *build_mode); + + proto::BuildResult proto_res{}; + proto_res.set_status(res.status_to_proto()); + + if (!res.errorMsg.empty()) { + proto_res.set_msg(res.errorMsg); + } - response->set_status(res.status_to_proto()); - response->set_error_message(res.errorMsg); + proto::BuildEvent event{}; + *event.mutable_result() = proto_res; + writer->Write(event); return Status::OK; }, __FUNCTION__); diff --git a/third_party/nix/src/proto/worker.proto b/third_party/nix/src/proto/worker.proto index fe89b292a2e5..6a80b3e32b42 100644 --- a/third_party/nix/src/proto/worker.proto +++ b/third_party/nix/src/proto/worker.proto @@ -27,7 +27,7 @@ service WorkerService { // Build the specified derivations in one of the specified build // modes, defaulting to a normal build. - rpc BuildPaths(BuildPathsRequest) returns (google.protobuf.Empty); + rpc BuildPaths(BuildPathsRequest) returns (stream BuildEvent); // TODO: What does this do? rpc EnsurePath(StorePath) returns (google.protobuf.Empty); @@ -90,7 +90,7 @@ service WorkerService { // Build a single non-materialized derivation (i.e. not from an // on-disk .drv file). - rpc BuildDerivation(BuildDerivationRequest) returns (BuildDerivationResponse); + rpc BuildDerivation(BuildDerivationRequest) returns (stream BuildEvent); // Add signatures to the specified store path. The signatures are not // verified. @@ -174,6 +174,32 @@ message Signatures { repeated string sigs = 1; } +// Represents the outcome of a build for a single store path. +message BuildResult { + StorePath path = 1; + BuildStatus status = 2; + string msg = 3; +} + +// Represents an event occuring during a build. +message BuildEvent { + message LogLine { + string line = 1; + StorePath path = 2; + } + + oneof result_type { + // Build for a store path has finished + BuildResult result = 1; + + // A line of build log output was produced + LogLine build_log = 2; + + // Build for a store path has started + StorePath building_path = 3; + } +} + message IsValidPathResponse { bool is_valid = 1; } @@ -316,11 +342,6 @@ message BuildDerivationRequest { BuildMode build_mode = 3; } -message BuildDerivationResponse { - BuildStatus status = 1; - string error_message = 2; -} - message AddSignaturesRequest { StorePath path = 1; Signatures sigs = 2; |