summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/execution_api/remote/bazel/bazel_cas_client.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/buildtool/execution_api/remote/bazel/bazel_cas_client.cpp b/src/buildtool/execution_api/remote/bazel/bazel_cas_client.cpp
index 552fab3c..aa6b7c9f 100644
--- a/src/buildtool/execution_api/remote/bazel/bazel_cas_client.cpp
+++ b/src/buildtool/execution_api/remote/bazel/bazel_cas_client.cpp
@@ -489,6 +489,7 @@ auto BazelCasClient::FindMissingBlobs(std::string const& instance_name,
return result;
}
+// NOLINTNEXTLINE(misc-no-recursion)
auto BazelCasClient::BatchUpdateBlobs(
std::string const& instance_name,
std::vector<gsl::not_null<BazelBlob const*>>::const_iterator const& begin,
@@ -569,6 +570,29 @@ auto BazelCasClient::BatchUpdateBlobs(
return oss.str();
});
+ auto missing = std::distance(begin, end) - result.size();
+ if (not result.empty() and missing > 0) {
+ // The remote execution protocol is a bit unclear about how to deal with
+ // blob updates for which we got no response. While some clients
+ // consider a blob update failed only if a failed response is received,
+ // we are going extra defensive here and also consider missing responses
+ // to be a failed blob update. Issue a retry for the missing blobs.
+ logger_.Emit(LogLevel::Trace, "Retrying with missing blobs");
+ auto received_digests =
+ std::unordered_set<bazel_re::Digest>{result.begin(), result.end()};
+ auto missing_blobs = std::vector<gsl::not_null<BazelBlob const*>>{};
+ missing_blobs.reserve(missing);
+ std::for_each(
+ begin, end, [&received_digests, &missing_blobs](auto const& blob) {
+ if (not received_digests.contains(blob->digest)) {
+ missing_blobs.emplace_back(blob);
+ }
+ });
+ return result.size() + BatchUpdateBlobs(instance_name,
+ missing_blobs.begin(),
+ missing_blobs.end());
+ }
+
return result.size();
}