refactore

This commit is contained in:
Valentin Balaschenko
2026-02-26 16:28:26 +00:00
parent 21367d49fb
commit cb26308ba3
5 changed files with 275 additions and 21 deletions

View File

@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h>
#include <xrpl/basics/contract.h>
#include <xrpl/server/FDGuard.h>
#include <xrpl/server/detail/ExponentialBackoff.h>
#include <xrpl/server/detail/PlainHTTPPeer.h>
#include <xrpl/server/detail/SSLHTTPPeer.h>
#include <xrpl/server/detail/io_list.h>
@@ -83,9 +84,7 @@ private:
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
bool ssl_;
bool plain_;
static constexpr std::chrono::milliseconds INITIAL_ACCEPT_DELAY{50};
static constexpr std::chrono::milliseconds MAX_ACCEPT_DELAY{2000};
std::chrono::milliseconds accept_delay_{INITIAL_ACCEPT_DELAY};
ExponentialBackoff backoff_;
boost::asio::steady_timer backoff_timer_;
void
@@ -317,11 +316,11 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
{
if (FDGuard::should_throttle(0.70))
{
backoff_timer_.expires_after(accept_delay_);
backoff_timer_.expires_after(backoff_.current());
boost::system::error_code tec;
backoff_timer_.async_wait(do_yield[tec]);
accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY);
JLOG(j_.warn()) << "Throttling do_accept for " << accept_delay_.count() << "ms.";
auto const delay = backoff_.increase();
JLOG(j_.warn()) << "Throttling do_accept for " << delay.count() << "ms.";
continue;
}
@@ -338,14 +337,15 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
if (ec == boost::asio::error::no_descriptors ||
ec == boost::asio::error::no_buffer_space)
{
auto const delay = backoff_.current();
JLOG(j_.warn()) << "accept: Too many open files. Pausing for "
<< accept_delay_.count() << "ms.";
<< delay.count() << "ms.";
backoff_timer_.expires_after(accept_delay_);
backoff_timer_.expires_after(delay);
boost::system::error_code tec;
backoff_timer_.async_wait(do_yield[tec]);
accept_delay_ = std::min(accept_delay_ * 2, MAX_ACCEPT_DELAY);
backoff_.increase();
}
else
{
@@ -354,7 +354,7 @@ Door<Handler>::do_accept(boost::asio::yield_context do_yield)
continue;
}
accept_delay_ = INITIAL_ACCEPT_DELAY;
backoff_.reset();
if (ssl_ && plain_)
{

View File

@@ -0,0 +1,93 @@
#pragma once
#include <chrono>
#include <algorithm>
namespace xrpl {
/**
* @brief Exponential backoff delay manager with configurable limits.
*
* Manages delay values that double on each increase (capped at maximum)
* and can be reset to initial value. Used for throttling accept() calls
* when file descriptor pressure is detected.
*/
class ExponentialBackoff
{
public:
using duration_type = std::chrono::milliseconds;
static constexpr duration_type DEFAULT_INITIAL_DELAY{50};
static constexpr duration_type DEFAULT_MAX_DELAY{2000};
/**
* @brief Construct with custom or default delay parameters.
*
* @param initial Initial delay value (default: 50ms)
* @param maximum Maximum delay cap (default: 2000ms)
*/
explicit ExponentialBackoff(
duration_type initial = DEFAULT_INITIAL_DELAY,
duration_type maximum = DEFAULT_MAX_DELAY)
: initial_(initial), maximum_(maximum), current_(initial)
{
}
/**
* @brief Get current delay value.
*/
[[nodiscard]] duration_type
current() const noexcept
{
return current_;
}
/**
* @brief Double the current delay, capped at maximum.
*
* @return The new current delay value after increase.
*/
duration_type
increase() noexcept
{
current_ = std::min(current_ * 2, maximum_);
return current_;
}
/**
* @brief Reset delay to initial value.
*
* @return The initial delay value.
*/
duration_type
reset() noexcept
{
current_ = initial_;
return current_;
}
/**
* @brief Get initial delay value.
*/
[[nodiscard]] duration_type
initial() const noexcept
{
return initial_;
}
/**
* @brief Get maximum delay value.
*/
[[nodiscard]] duration_type
maximum() const noexcept
{
return maximum_;
}
private:
duration_type const initial_;
duration_type const maximum_;
duration_type current_;
};
} // namespace xrpl