summaryrefslogtreecommitdiff
path: root/src/buildtool/common/remote/retry.cpp
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2024-07-18 15:49:01 +0200
committerPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2024-07-19 09:50:37 +0200
commit2361355beb80685157b2a0cf6f79c14e010a00de (patch)
treef4377b6d02e3ae33f12a27b00ce4a0cd1853cb55 /src/buildtool/common/remote/retry.cpp
parent741773f63fa24d2c862db32cb46a0edfbd69968b (diff)
downloadjustbuild-2361355beb80685157b2a0cf6f79c14e010a00de.tar.gz
WithRetry: Replace template parameters by std::function
Now also requires guarding for bootstrapping to not bring in grpc.
Diffstat (limited to 'src/buildtool/common/remote/retry.cpp')
-rw-r--r--src/buildtool/common/remote/retry.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/buildtool/common/remote/retry.cpp b/src/buildtool/common/remote/retry.cpp
new file mode 100644
index 00000000..5d75585c
--- /dev/null
+++ b/src/buildtool/common/remote/retry.cpp
@@ -0,0 +1,112 @@
+// Copyright 2024 Huawei Cloud Computing Technology Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/buildtool/common/remote/retry.hpp"
+#ifndef BOOTSTRAP_BUILD_TOOL
+
+#include <chrono>
+#include <thread>
+
+#include "src/buildtool/common/remote/retry_config.hpp"
+#include "src/buildtool/logging/log_level.hpp"
+
+auto WithRetry(CallableReturningRetryResponse const& f,
+ Logger const& logger) noexcept -> bool {
+ try {
+ auto const& attempts = RetryConfig::GetMaxAttempts();
+ for (auto attempt = 1U; attempt <= attempts; ++attempt) {
+ auto [ok, fatal, error_msg] = f();
+ if (ok) {
+ return true;
+ }
+ if (fatal) {
+ if (error_msg) {
+ logger.Emit(LogLevel::Error, "{}", *error_msg);
+ }
+ return false;
+ }
+ // don't wait if it was the last attempt
+ if (attempt < attempts) {
+ auto const sleep_for_seconds =
+ RetryConfig::GetSleepTimeSeconds(attempt);
+ logger.Emit(kRetryLogLevel,
+ "Attempt {}/{} failed{} Retrying in {} seconds.",
+ attempt,
+ attempts,
+ error_msg ? fmt::format(": {}", *error_msg) : ".",
+ sleep_for_seconds);
+ std::this_thread::sleep_for(
+ std::chrono::seconds(sleep_for_seconds));
+ }
+ else {
+ if (error_msg) {
+ logger.Emit(LogLevel::Error,
+ "After {} attempts: {}",
+ attempt,
+ *error_msg);
+ }
+ }
+ }
+ } catch (...) {
+ logger.Emit(LogLevel::Error, "WithRetry: caught unknown exception");
+ }
+ return false;
+}
+auto WithRetry(CallableReturningGrpcStatus const& f,
+ Logger const& logger) noexcept -> std::pair<bool, grpc::Status> {
+ grpc::Status status{};
+ try {
+ auto attempts = RetryConfig::GetMaxAttempts();
+ for (auto attempt = 1U; attempt <= attempts; ++attempt) {
+ status = f();
+ if (status.ok() or
+ status.error_code() != grpc::StatusCode::UNAVAILABLE) {
+ return {status.ok(), std::move(status)};
+ }
+ // don't wait if it was the last attempt
+ if (attempt < attempts) {
+ auto const sleep_for_seconds =
+ RetryConfig::GetSleepTimeSeconds(attempt);
+ logger.Emit(
+ kRetryLogLevel,
+ "Attempt {}/{} failed: {}: {}: Retrying in {} seconds.",
+ attempt,
+ attempts,
+ static_cast<int>(status.error_code()),
+ status.error_message(),
+ sleep_for_seconds);
+ std::this_thread::sleep_for(
+ std::chrono::seconds(sleep_for_seconds));
+ }
+ else {
+ // The caller performs a second check on the
+ // status.error_code(), and, eventually, emits to Error level
+ // there.
+ //
+ // To avoid duplication of similar errors, we emit to Debug
+ // level.
+ logger.Emit(LogLevel::Debug,
+ "After {} attempts: {}: {}",
+ attempt,
+ static_cast<int>(status.error_code()),
+ status.error_message());
+ }
+ }
+ } catch (...) {
+ logger.Emit(LogLevel::Error, "WithRetry: caught unknown exception");
+ }
+ return {false, std::move(status)};
+}
+
+#endif // BOOTSTRAP_BUILD_TOOL