coinprices/PriceRetryPolicy.cpp¶
Namespaces¶
| Name |
|---|
| sgns |
Functions¶
| Name | |
|---|---|
| bool | IsTransientTransport(http::ClientError error) Pre-mapping classifier over the transport's own error enum — true for ClientError::TIMEOUT / CONNECT_FAILED / RESOLVE_FAILED only. |
| bool | IsTransient(const PriceFetchFailure & error) True only for transport-class failures (D-11): timeouts, connection resets, DNS failures. NEVER true for a status-bearing failure (403/429/any HTTP status), parse errors, or input errors. |
| RetryDecision | ShouldRetry(const PriceFetchFailure & error, int attempt, const RetryConfig & config) Decide whether to make another attempt after a failure. |
Functions Documentation¶
function IsTransientTransport¶
Pre-mapping classifier over the transport's own error enum — true for ClientError::TIMEOUT / CONNECT_FAILED / RESOLVE_FAILED only.
function IsTransient¶
True only for transport-class failures (D-11): timeouts, connection resets, DNS failures. NEVER true for a status-bearing failure (403/429/any HTTP status), parse errors, or input errors.
function ShouldRetry¶
RetryDecision ShouldRetry(
const PriceFetchFailure & error,
int attempt,
const RetryConfig & config
)
Decide whether to make another attempt after a failure.
Parameters:
- error The failure from the just-finished attempt
- attempt 1-based index of the attempt that just failed
- config The retry schedule in force
Return: Retry iff the error is transient AND attempt < maxAttempts; GiveUp otherwise (403/429 fall through immediately by construction)
Source code¶
#include "PriceRetryPolicy.hpp"
namespace sgns
{
bool IsTransientTransport( http::ClientError error )
{
switch ( error )
{
case http::ClientError::TIMEOUT:
case http::ClientError::CONNECT_FAILED:
case http::ClientError::RESOLVE_FAILED:
return true;
case http::ClientError::TLS_HANDSHAKE_FAILED:
case http::ClientError::TLS_CA_LOAD_FAILED:
case http::ClientError::WRITE_FAILED:
case http::ClientError::READ_INTERRUPTED:
case http::ClientError::NO_HEADER:
break;
}
return false;
}
bool IsTransient( const PriceFetchFailure &error )
{
// Only pure transport failures are retryable (D-11): any HTTP status
// at all (403/429/404/5xx...) means the server answered — retrying
// cannot change the answer.
if ( error.httpStatus != 0 )
{
return false;
}
if ( error.code != PriceFetchError::NetworkError )
{
return false;
}
// D-14 — strict transport gating: TLS-handshake/CA-load/write
// failures stop being blindly retried; only TIMEOUT/CONNECT_FAILED/
// RESOLVE_FAILED (per IsTransientTransport) are transient. An
// UNCLASSIFIED {NetworkError, 0} is NOT transient — every facade
// path populates the field.
return error.transportError && IsTransientTransport( *error.transportError );
}
RetryDecision ShouldRetry( const PriceFetchFailure &error, int attempt, const RetryConfig &config )
{
if ( !IsTransient( error ) )
{
return RetryDecision::GiveUp;
}
if ( attempt >= config.maxAttempts )
{
return RetryDecision::GiveUp;
}
return RetryDecision::Retry;
}
} // namespace sgns
Updated on 2026-10-09 at 04:02:50 +0000