diff options
author | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-11-20 14:15:32 +0100 |
---|---|---|
committer | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-11-21 10:21:29 +0100 |
commit | 5fee8034265676b903618d19a7d7d65bb8d4b023 (patch) | |
tree | 8e18072885a63871509e5c2e5460442673d407b3 | |
parent | 232686826d31e55e739643789b4b67aed8468016 (diff) | |
download | justbuild-5fee8034265676b903618d19a7d7d65bb8d4b023.tar.gz |
just serve: Implement server-side ServeContent RPC
-rw-r--r-- | src/buildtool/serve_api/serve_service/source_tree.cpp | 73 | ||||
-rw-r--r-- | src/buildtool/serve_api/serve_service/source_tree.hpp | 11 |
2 files changed, 84 insertions, 0 deletions
diff --git a/src/buildtool/serve_api/serve_service/source_tree.cpp b/src/buildtool/serve_api/serve_service/source_tree.cpp index 8351d8d9..4ce09983 100644 --- a/src/buildtool/serve_api/serve_service/source_tree.cpp +++ b/src/buildtool/serve_api/serve_service/source_tree.cpp @@ -684,3 +684,76 @@ auto SourceTreeService::ServeArchiveTree( request->sync_tree(), response); } + +auto SourceTreeService::ServeContent( + ::grpc::ServerContext* /* context */, + const ::justbuild::just_serve::ServeContentRequest* request, + ServeContentResponse* response) -> ::grpc::Status { + auto const& content{request->content()}; + // acquire lock for CAS + auto lock = GarbageCollector::SharedLock(); + if (!lock) { + auto str = fmt::format("Could not acquire gc SharedLock"); + logger_->Emit(LogLevel::Error, str); + response->set_status(ServeContentResponse::INTERNAL_ERROR); + return ::grpc::Status::OK; + } + // check if content blob is in Git cache + if (auto data = + GetBlobFromRepo(StorageConfig::GitRoot(), content, logger_)) { + // upload blob to remote CAS + auto digest = ArtifactDigest{content, 0, /*is_tree=*/false}; + auto repo = RepositoryConfig{}; + if (not repo.SetGitCAS(StorageConfig::GitRoot())) { + auto str = fmt::format("Failed to SetGitCAS at {}", + StorageConfig::GitRoot().string()); + logger_->Emit(LogLevel::Error, str); + response->set_status(ServeContentResponse::INTERNAL_ERROR); + return ::grpc::Status::OK; + } + auto git_api = GitApi{&repo}; + if (not git_api.RetrieveToCas( + {Artifact::ObjectInfo{.digest = digest, + .type = ObjectType::File}}, + &(*remote_api_))) { + auto str = fmt::format("Failed to sync content {}", content); + logger_->Emit(LogLevel::Error, str); + response->set_status(ServeContentResponse::SYNC_ERROR); + return ::grpc::Status::OK; + } + // success! + response->set_status(ServeContentResponse::OK); + return ::grpc::Status::OK; + } + // check if content blob is in a known repository + for (auto const& path : RemoteServeConfig::KnownRepositories()) { + if (auto data = GetBlobFromRepo(path, content, logger_)) { + // upload blob to remote CAS + auto digest = ArtifactDigest{content, 0, /*is_tree=*/false}; + auto repo = RepositoryConfig{}; + if (not repo.SetGitCAS(path)) { + auto str = fmt::format("Failed to SetGitCAS at {}", + StorageConfig::GitRoot().string()); + logger_->Emit(LogLevel::Error, str); + response->set_status(ServeContentResponse::INTERNAL_ERROR); + return ::grpc::Status::OK; + } + auto git_api = GitApi{&repo}; + if (not git_api.RetrieveToCas( + {Artifact::ObjectInfo{.digest = digest, + .type = ObjectType::File}}, + &(*remote_api_))) { + auto str = fmt::format("Failed to sync content {}", content); + logger_->Emit(LogLevel::Error, str); + response->set_status(ServeContentResponse::SYNC_ERROR); + return ::grpc::Status::OK; + } + // success! + response->set_status(ServeContentResponse::OK); + return ::grpc::Status::OK; + } + } + // content blob not known + response->set_status(ServeContentResponse::NOT_FOUND); + return ::grpc::Status::OK; +} diff --git a/src/buildtool/serve_api/serve_service/source_tree.hpp b/src/buildtool/serve_api/serve_service/source_tree.hpp index 030d33ee..db64d693 100644 --- a/src/buildtool/serve_api/serve_service/source_tree.hpp +++ b/src/buildtool/serve_api/serve_service/source_tree.hpp @@ -41,6 +41,8 @@ class SourceTreeService final using ServeArchiveTreeResponse = ::justbuild::just_serve::ServeArchiveTreeResponse; + using ServeContentResponse = ::justbuild::just_serve::ServeContentResponse; + // Retrieve the Git-subtree identifier from a given Git commit. // // There are no method-specific errors. @@ -58,6 +60,15 @@ class SourceTreeService final const ::justbuild::just_serve::ServeArchiveTreeRequest* request, ServeArchiveTreeResponse* response) -> ::grpc::Status override; + // Make the blob identifier of an archive content available in + // remote CAS, if blob is known. + // + // There are no method-specific errors. + auto ServeContent( + ::grpc::ServerContext* context, + const ::justbuild::just_serve::ServeContentRequest* request, + ServeContentResponse* response) -> ::grpc::Status override; + private: mutable std::shared_mutex mutex_; std::shared_ptr<Logger> logger_{std::make_shared<Logger>("serve-service")}; |