Lightweight 0.20260921.0
Loading...
Searching...
No Matches
Lightweight::SqlRetryPolicy Class Reference

A reusable retry/backoff policy for transient database failures. More...

#include <SqlRetryPolicy.hpp>

Public Types

using RetryObserver = std::function< void(SqlRetryAttempt const &)>
 

Public Member Functions

 SqlRetryPolicy ()=default
 
LIGHTWEIGHT_API SqlRetryPolicy (SqlRetrySettings settings, SqlRetryClassifier const *classifier=nullptr, SqlRetrySleeper *sleeper=nullptr, RetryObserver observer={})
 
SqlRetrySettings const & Settings () const noexcept
 
SqlRetryClassifier const & Classifier () const noexcept
 
void SetRetryObserver (RetryObserver observer)
 
LIGHTWEIGHT_API std::chrono::milliseconds DelayFor (unsigned retryIndex) const noexcept
 
LIGHTWEIGHT_API SqlRetryDecision Decide (SqlErrorInfo const &error, SqlRetryState const &state) const noexcept
 
template<typename Callable >
auto Execute (Callable callable) const -> std::invoke_result_t< Callable & >
 
template<typename Callable >
auto TryExecute (Callable callable) const -> std::expected< std::invoke_result_t< Callable & >, SqlErrorInfo >
 

Static Public Member Functions

static LIGHTWEIGHT_API SqlRetryPolicy For (SqlServerType serverType, SqlRetrySettings settings={})
 
static LIGHTWEIGHT_API SqlRetryPolicy For (SqlConnection const &connection, SqlRetrySettings settings={})
 

Detailed Description

A reusable retry/backoff policy for transient database failures.

Combines a SqlRetryClassifier (which errors are worth another attempt — a per-DBMS question) with SqlRetrySettings (how many attempts, how long to wait between them). Every collaborator is injectable, and none of them is constructed internally: the classifier and the sleeper are borrowed references with sensible process-wide defaults.

The type separates the decision from the driving:

  • Decide is pure. Given an error and how far the loop has already got, it says retry or give up, and why. No clock, no sleep, no I/O — so every branch is reachable from a unit test.
  • Execute / TryExecute are the thin drivers that call Decide in a loop, wait via the injected SqlRetrySleeper, and re-run the callable.
auto const policy = SqlRetryPolicy::For(connection);
auto const orderCount = policy.Execute([&] {
return SqlStatement { connection }
.ExecuteDirectScalar<int>("SELECT COUNT(*) FROM orders")
.value_or(0);
});
static LIGHTWEIGHT_API SqlRetryPolicy For(SqlServerType serverType, SqlRetrySettings settings={})
High level API for (prepared) raw SQL statements.
std::optional< T > ExecuteDirectScalar(std::string_view const &query, std::source_location location=std::source_location::current())
Note
The callable must be safe to run more than once. Retrying an operation that already had a visible side effect is the caller's responsibility; wrap it in a transaction that the callable itself begins and commits, so a retry starts from a clean slate.

Definition at line 188 of file SqlRetryPolicy.hpp.

Member Typedef Documentation

◆ RetryObserver

using Lightweight::SqlRetryPolicy::RetryObserver = std::function<void(SqlRetryAttempt const&)>

Notified just before each retry. Used, for instance, to route retry notices into a progress reporter or a log.

Definition at line 193 of file SqlRetryPolicy.hpp.

Constructor & Destructor Documentation

◆ SqlRetryPolicy() [1/2]

Lightweight::SqlRetryPolicy::SqlRetryPolicy ( )
default

Constructs a policy with the default settings, the dialect-agnostic classifier and the real sleeper.

◆ SqlRetryPolicy() [2/2]

LIGHTWEIGHT_API Lightweight::SqlRetryPolicy::SqlRetryPolicy ( SqlRetrySettings  settings,
SqlRetryClassifier const *  classifier = nullptr,
SqlRetrySleeper *  sleeper = nullptr,
RetryObserver  observer = {} 
)
explicit

Constructs a policy.

Parameters
settingsThe backoff configuration.
classifierWhich errors are retryable; nullptr selects GenericRetryOps(). The referenced classifier must outlive the policy — the dialect singletons always do.
sleeperHow to wait between attempts; nullptr selects ThreadSleeper(). The referenced sleeper must outlive the policy.
observerCalled before each retry; may be empty.

Member Function Documentation

◆ For() [1/2]

static LIGHTWEIGHT_API SqlRetryPolicy Lightweight::SqlRetryPolicy::For ( SqlServerType  serverType,
SqlRetrySettings  settings = {} 
)
static

Builds a policy whose classifier matches the given server type.

The mapping runs through SqlQueryFormatter::Get(), so the per-DBMS knowledge stays at the formatter dispatch point. A server type without a formatter of its own falls back to GenericRetryOps().

Parameters
serverTypeThe DBMS whose error dialect should be used.
settingsThe backoff configuration.
Returns
The configured policy.

◆ For() [2/2]

static LIGHTWEIGHT_API SqlRetryPolicy Lightweight::SqlRetryPolicy::For ( SqlConnection const &  connection,
SqlRetrySettings  settings = {} 
)
static

Builds a policy whose classifier matches the connection's DBMS.

Parameters
connectionThe connection whose server type selects the classifier.
settingsThe backoff configuration.
Returns
The configured policy.

◆ Settings()

SqlRetrySettings const & Lightweight::SqlRetryPolicy::Settings ( ) const
inlinenoexcept
Returns
The backoff configuration in effect.

Definition at line 232 of file SqlRetryPolicy.hpp.

◆ Classifier()

SqlRetryClassifier const & Lightweight::SqlRetryPolicy::Classifier ( ) const
inlinenoexcept
Returns
The classifier in effect.

Definition at line 238 of file SqlRetryPolicy.hpp.

◆ SetRetryObserver()

void Lightweight::SqlRetryPolicy::SetRetryObserver ( RetryObserver  observer)
inline

Installs an observer notified before each retry.

Parameters
observerThe observer; pass an empty function to remove a previously set one.

Definition at line 246 of file SqlRetryPolicy.hpp.

◆ DelayFor()

LIGHTWEIGHT_API std::chrono::milliseconds Lightweight::SqlRetryPolicy::DelayFor ( unsigned  retryIndex) const
noexcept

Computes the backoff delay preceding a given retry.

Parameters
retryIndexZero-based retry number: 0 is the delay before the first retry.
Returns
initialDelay multiplied by backoffMultiplier retryIndex times, clamped to maxDelay.

◆ Decide()

LIGHTWEIGHT_API SqlRetryDecision Lightweight::SqlRetryPolicy::Decide ( SqlErrorInfo const &  error,
SqlRetryState const &  state 
) const
noexcept

Decides what to do after a failed attempt.

Pure: no I/O, no clock, no hidden state.

Parameters
errorThe error reported by the failed attempt.
stateHow far the retry loop has already got.
Returns
Whether to retry, how long to wait first, and — if not — why not.

◆ Execute()

template<typename Callable >
auto Lightweight::SqlRetryPolicy::Execute ( Callable  callable) const -> std::invoke_result_t<Callable&>

Runs callable, retrying while the policy says the failure is worth another attempt.

Only SqlException is treated as a retry candidate; any other exception propagates immediately. When the policy gives up, the last SqlException is rethrown unchanged, so the caller sees the original diagnostics rather than a wrapper.

Template Parameters
CallableA nullary callable, taken by value because it is invoked repeatedly.
Parameters
callableThe operation to run.
Returns
Whatever callable returns.

Definition at line 298 of file SqlRetryPolicy.hpp.

References GiveUp, and Lightweight::SqlRetryAttempt::retryNumber.

◆ TryExecute()

template<typename Callable >
auto Lightweight::SqlRetryPolicy::TryExecute ( Callable  callable) const -> std::expected<std::invoke_result_t<Callable&>, SqlErrorInfo>

Like Execute, but reports a final failure as std::unexpected rather than throwing.

Template Parameters
CallableA nullary callable, taken by value because it is invoked repeatedly.
Parameters
callableThe operation to run.
Returns
The callable's result, or the SqlErrorInfo of the attempt the policy gave up on.

Definition at line 328 of file SqlRetryPolicy.hpp.

References Execute.


The documentation for this class was generated from the following file: