7#include "SqlRetryClassifier.hpp"
8#include "SqlServerType.hpp"
110 [[nodiscard]]
constexpr explicit operator bool() const noexcept
154 virtual void Sleep(std::chrono::milliseconds duration) = 0;
248 _observer = std::move(observer);
256 [[nodiscard]] LIGHTWEIGHT_API std::chrono::milliseconds
DelayFor(
unsigned retryIndex)
const noexcept;
277 template <
typename Callable>
278 auto Execute(Callable callable)
const -> std::invoke_result_t<Callable&>;
285 template <
typename Callable>
286 [[nodiscard]]
auto TryExecute(Callable callable)
const -> std::expected<std::invoke_result_t<Callable&>,
SqlErrorInfo>;
289 LIGHTWEIGHT_API
void NotifyRetry(
SqlRetryAttempt const& attempt)
const;
294 RetryObserver _observer {};
297template <
typename Callable>
308 catch (SqlException
const& e)
310 auto const decision = Decide(e.info(), state);
314 state.retriesSoFar += 1;
315 state.delaySoFar += decision.delay;
318 .maxRetries = _settings.maxRetries,
319 .delay = decision.delay,
320 .error = e.info() });
322 _sleeper->Sleep(decision.delay);
327template <
typename Callable>
330 using Result = std::invoke_result_t<Callable&>;
334 if constexpr (std::is_void_v<Result>)
340 return Execute(std::move(callable));
342 catch (SqlException
const& e)
344 return std::unexpected { e.info() };
Represents a connection to a SQL database.
Dialect-specific classification of SQL errors into transient and permanent.
A reusable retry/backoff policy for transient database failures.
LIGHTWEIGHT_API std::chrono::milliseconds DelayFor(unsigned retryIndex) const noexcept
auto TryExecute(Callable callable) const -> std::expected< std::invoke_result_t< Callable & >, SqlErrorInfo >
void SetRetryObserver(RetryObserver observer)
static LIGHTWEIGHT_API SqlRetryPolicy For(SqlConnection const &connection, SqlRetrySettings settings={})
SqlRetrySettings const & Settings() const noexcept
static LIGHTWEIGHT_API SqlRetryPolicy For(SqlServerType serverType, SqlRetrySettings settings={})
LIGHTWEIGHT_API SqlRetryDecision Decide(SqlErrorInfo const &error, SqlRetryState const &state) const noexcept
std::function< void(SqlRetryAttempt const &)> RetryObserver
LIGHTWEIGHT_API SqlRetryPolicy(SqlRetrySettings settings, SqlRetryClassifier const *classifier=nullptr, SqlRetrySleeper *sleeper=nullptr, RetryObserver observer={})
auto Execute(Callable callable) const -> std::invoke_result_t< Callable & >
SqlRetryClassifier const & Classifier() const noexcept
Supplies the wait between retries.
virtual void Sleep(std::chrono::milliseconds duration)=0
virtual ~SqlRetrySleeper()=default
Polymorphic destructor.
@ Execute
SQLExecute of a prepared statement.
LIGHTWEIGHT_API SqlRetryClassifier const & GenericRetryOps() noexcept
Returns the dialect-agnostic classifier.
LIGHTWEIGHT_API SqlRetrySleeper & ThreadSleeper() noexcept
Returns the production sleeper, which forwards to std::this_thread::sleep_for.
@ Retry
Wait for SqlRetryDecision::delay and try again.
@ GiveUp
Surface the failure to the caller.
@ RetriesExhausted
The error was transient, but SqlRetrySettings::maxRetries is spent.
@ NotTransient
The error is permanent; another attempt would fail identically.
@ None
Not giving up — set when the action is SqlRetryAction::Retry.
Represents an ODBC SQL error.
unsigned maxRetries
The configured budget, so an observer can render "retry 2/3" without holding the settings.
SqlErrorInfo error
The error that triggered the retry.
std::chrono::milliseconds delay
How long the driver is about to sleep before re-running the operation.
unsigned retryNumber
Which retry this is, counting from one.
std::chrono::milliseconds delay
SqlRetryAction action
Whether to retry or to surface the failure.
SqlRetryGiveUpReason reason
Why the policy gave up. SqlRetryGiveUpReason::None when it did not.
std::chrono::milliseconds initialDelay
Delay before the first retry.
double backoffMultiplier
Multiplier applied to the delay after each failed attempt (exponential backoff).
std::chrono::milliseconds maxDelay
Upper bound on any single delay, so a long budget cannot produce an unbounded wait.
std::chrono::milliseconds totalDelayBudget
unsigned retriesSoFar
Number of retries already consumed. Zero on the first failure.
std::chrono::milliseconds delaySoFar