blob: 7fee645f4c28e29ac7653691fcf90ff17a42028a [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <cmath>
#include <stdexcept>
#include "layer.hpp"
#include "lib.rs.h"
namespace opendal {
FfiLayerBuilderMutator::FfiLayerBuilderMutator(ffi::LayerBuilder &builder)
: builder_(builder) {}
void FfiLayerBuilderMutator::AddTimeout(uint64_t timeout_ns,
uint64_t io_timeout_ns) {
builder_.add_timeout(timeout_ns, io_timeout_ns);
}
void FfiLayerBuilderMutator::AddRetry(bool jitter, float factor,
uint64_t min_delay_ns,
uint64_t max_delay_ns,
uint64_t max_times) {
builder_.add_retry(jitter, factor, min_delay_ns, max_delay_ns, max_times);
}
namespace {
void ValidateRetryConfig(const RetryConfig &config) {
if (config.max_times == 0) {
throw std::invalid_argument("retry max times must be positive");
}
if (std::isnan(config.factor) || std::isinf(config.factor) ||
config.factor < 1.0f) {
throw std::invalid_argument(
"retry factor must be finite and greater than or equal to 1");
}
if (config.min_delay.count() <= 0) {
throw std::invalid_argument("retry min delay must be positive");
}
if (config.max_delay.count() <= 0) {
throw std::invalid_argument("retry max delay must be positive");
}
if (config.max_delay < config.min_delay) {
throw std::invalid_argument(
"retry max delay must be greater than or equal to retry min delay");
}
}
class TimeoutOperatorOption final : public OperatorOption {
public:
TimeoutOperatorOption(std::chrono::nanoseconds timeout,
std::chrono::nanoseconds io_timeout)
: timeout_(timeout), io_timeout_(io_timeout) {}
void Apply(LayerBuilderMutator &builder) const override {
if (timeout_.count() <= 0) {
throw std::invalid_argument("timeout must be positive");
}
if (io_timeout_.count() <= 0) {
throw std::invalid_argument("io timeout must be positive");
}
builder.AddTimeout(static_cast<uint64_t>(timeout_.count()),
static_cast<uint64_t>(io_timeout_.count()));
}
private:
std::chrono::nanoseconds timeout_;
std::chrono::nanoseconds io_timeout_;
};
class RetryOperatorOption final : public OperatorOption {
public:
explicit RetryOperatorOption(RetryConfig config) : config_(config) {}
void Apply(LayerBuilderMutator &builder) const override {
ValidateRetryConfig(config_);
builder.AddRetry(
config_.jitter, config_.factor,
static_cast<uint64_t>(config_.min_delay.count()),
static_cast<uint64_t>(config_.max_delay.count()), config_.max_times);
}
private:
RetryConfig config_;
};
} // namespace
std::unique_ptr<OperatorOption> WithTimeout(
std::chrono::nanoseconds timeout, std::chrono::nanoseconds io_timeout) {
return std::make_unique<TimeoutOperatorOption>(timeout, io_timeout);
}
std::unique_ptr<OperatorOption> WithRetry(RetryConfig config) {
return std::make_unique<RetryOperatorOption>(config);
}
std::vector<std::unique_ptr<OperatorOption>> DefaultBehaviorLayerOptions() {
std::vector<std::unique_ptr<OperatorOption>> options;
options.push_back(WithTimeout(std::chrono::minutes(1),
std::chrono::seconds(10)));
options.push_back(WithRetry());
return options;
}
} // namespace opendal